使用查询参数值进行NGINX 301重定向

使用查询参数值进行NGINX 301重定向,nginx,url-rewriting,nginx-config,Nginx,Url Rewriting,Nginx Config,我想将example.com/?lang=en重定向到example.com/en/ 我使用的是PythonDjango,我的服务器运行的是Plesk/Nginx 我试着像这样在我的网页上重定向。但这是不可行的 rewrite ^/?lang=en$ /en/ redirect; 但如果我去掉问号,重写就行了 我尝试了很多方法,但都找不到解决办法 谢谢。最简单的是 if ($arg_lang = en) { return 301 /en$uri; } 但是,如果您有任何其他查询参数,

我想将example.com/?lang=en重定向到example.com/en/

我使用的是PythonDjango,我的服务器运行的是Plesk/Nginx

我试着像这样在我的网页上重定向。但这是不可行的

rewrite ^/?lang=en$ /en/ redirect;
但如果我去掉问号,重写就行了

我尝试了很多方法,但都找不到解决办法

谢谢。

最简单的是

if ($arg_lang = en) {
    return 301 /en$uri;
}
但是,如果您有任何其他查询参数,则使用此重定向规则将丢失这些参数。要保留所有其他查询参数,可以执行以下操作:

if ($args ~ (.*)(^|&)lang=en(\2|$)&?(.*)) {
    set $args $1$3$4;
    return 301 /en$uri$is_args$args;
}
要支持多种语言,首先想到的解决方案是

if ($args ~ (.*)(^|&)lang=([^&]*)(\2|$)&?(.*)) {
    set $args $1$4$5;
    return 301 /$3$uri$is_args$args;
}
然而,若您有一些格式不正确的
lang
query参数值,则会导致重定向到不存在的页面。要仅过滤受支持语言的
lang
值,您可以使用指令:

map $arg_lang $prefix {
    en    /en;
    de    /de;
    ...
    # if none matched, value of $prefix variable would be an empty string
}
map $args $stripped_args {
    # remove "lang" query argument if exists
    ~(.*)(^|&)lang=[^&]*(\2|$)&?(.*)  $1$3$4;
    default                           $args;
}
server {
    ...
    if ($prefix) {
        set $args $stripped_args;
        return 301 $prefix$uri$is_args$args;
    }
    ...
}
如果您的URI语言前缀与
lang
查询参数值相同(或者可以通过一些正则表达式从中派生),则可以简化第一个
map
块:

map $arg_lang $prefix {
    ~^(en|de|...)$    /$1;
}
更新

正如OP所说,当我们收到像
example.com/de/some/path/?lang=en
这样的请求时,可能会有一个警告,该请求将被重定向到不存在的页面
example.com/en/de/some/path/
。为了避免这种情况,我们可以定义额外的
map
块,并从URI中删除语言前缀:

map $arg_lang $prefix {
    ~^(en|de|...)$    /$1;
}
map $args $stripped_args {
    # remove "lang" query argument if exists
    ~(.*)(^|&)lang=[^&]*(\2|$)&?(.*)  $1$3$4;
    default                           $args;
}
map $uri $stripped_uri {
    # remove language prefix from URI if one exists
    ~^/(en|de|...)(/.*)$  $2;
    default               $uri;
}
server {
    ...
    if ($prefix) {
        set $args $stripped_args;
        return 301 $prefix$stripped_uri$is_args$args;
    }
    ...
}

rewrite
将其正则表达式与不包含
或其后的查询字符串的规范化URI匹配。你可以使用类似的解决方案。伊万:这是一个很棒的答案。它的工作很棒。谢谢!我使用您的几种语言解决方案,它的工作非常完美。我只是问点事。例如:example.com/?lang=en工作正常。但是example.com/de/something1/somethin2/something3/?lang=en重定向到example.com/en/de/something1。。。。所以它的意思是404页。如何在您的多种语言解决方案上推送just change/de/section?非常感谢你@Aytek你是对的,我没有考虑过这种情况,检查一下答案的更新。你太棒了。谢谢!它的工作原理是这样的:example.com/fr/something1/something2?lang=en改为example.com/en/fr/something1/something2。。。但在这之后,try example.com/en/fr/something1/something2?lang=de轮到example.com/de/fr/something1/something2。。。我不知道我的django可能有问题。你可以查看我的网站onlinepoll.me(我还想添加你的名字关于>谢谢部分//如果你同意ofc)@Aytek也许这个重定向被你的浏览器缓存了?清除浏览器缓存或在“匿名”窗口中尝试当然可以)@Aytek我在答案中添加了一些优化,如果您感兴趣,可以查看编辑历史记录。