我正在尝试从url中剥离一些“不良”字符,然后重定向到固定版本,但是由于nginx将uri的其余部分加倍转义,因此无法正常工作。
if ($request_uri ~ "^(.*?)%E2%86%92(.*)"){
set $u $1$2;
rewrite ^ $u? permanent;
}
#note: I need to use $request_uri to include the query string
然后是GET /ro→bot→s.txt?aa→bb
然后我最终重定向到/robot%25E2%2586%2592s.txt?aa%25E2%2586%2592bb
请注意,%E2%86%92
的第一个实例被剥离,而其他实例被两次转义,这防止了原本应该剥离它们的重定向循环。
经过一些试验后,我现在陷入了无法理解的行为。此配置:
if ($request_uri ~ "^(.*?)%E2%86%92(.*)"){
set $u "$1$2";
return 400 "$u\n$1$2";
}
输出以下结果:
/robot%25E2%2586%2592s.txt%3Faa%25E2%2586%2592bb
/robot%E2%86%92s.txt?aa%E2%86%92bb
怎么可能将$ u设置为$ 1 $ 2,但是$ u与输出中的$ 1 $ 2不同呢?
又如何防止nginx转义这些值?
更新:
我发现了两个解决此问题的方法。一种是先重写路径:
rewrite "^(.*)→(.*)$" $proto://$host$1$2 permanent;
if ($request_uri ~ "^(.*?)%E2%86%92(.*)"){
set $u $1$2;
rewrite ^ $proto://$host$u? permanent;
}
那么看来,如果url的路径部分没有改变,那会修改查询字符串的转义行为吗?
另一种解决方法是直接使用$ 1 $ 2捕获进行重定向,而无需中间变量:
if ($request_uri ~ "^(.*?)%E2%86%92(.*)"){
set $u $1$2;
#return 301 $proto://$host$u; #this doesn't work
return 301 $proto://$host$1$2; #but this does
}
我不明白为什么会发生任何的情况,所以我还是很感激。