mod_rewrite删除一个GET变量

Mik*_*ith 2 apache mod-rewrite get

我想抓住

example.com/home?lang=fr&foo=bar

并重定向到

example.com/fr/home?foo=bar

我试过了

    RewriteCond %{QUERY_STRING} lang=([a-z]{2})&?
    RewriteRule ^(.*) /%1/$1 [R=307]
Run Code Online (Sandbox Code Playgroud)

但我得到一个重定向循环.这是因为在将"fr"移动到请求字符串的前面之后,lang = fr不会从查询字符串中删除.这导致:

example.com/fr/fr/fr/fr/fr/fr/fr/fr/fr/....

我可以用

    RewriteRule ^(.*) /%1/$1? [R=307]
Run Code Online (Sandbox Code Playgroud)

但是这也从查询字符串中删除了foo = bar,我想保持原样

我找不到从查询字符串中只删除一个变量的方法.我确信有一个简单的解决方案,但谷歌没有帮助.谢谢

reg*_*ero 5

作为@whoisgregg回答(+1)的补充,这是一个很好的改编自apache wiki.那里的规则并不完美(例如,这个页面上的查询字符串的访问控制不会在一个小的urlencoding上抵制).

我们有一个针对测试用例的工作解决方案,但是一些扩展测试可能会失败:

RewriteCond %{QUERY_STRING} ^(.*)lang=([a-z]{2})&?(.*)$
RewriteRule (.*) /%2/$1?%1%3 [R=307]

foo.php?foo=bar&novlang=fr&toto=titi => /fr/foo.php?foo=bar&novtoto=titi
Run Code Online (Sandbox Code Playgroud)

这里lang=检测到零件,但如果任何参数以lang结尾,则会出现问题.

所以,我们需要一些修复,本周我一直在研究这个主题,这是一个更好的版本我认为:

RewriteCond %{QUERY_STRING} (.*)(^|&|%26|%20)lang(=|%3D)([^&]+)(.*)$
RewriteRule (.*) /%4/$1?%1%5 [R=307]

foo.php?foo=bar&novlang=fr&toto=titi => not matched (normal, no lang=)
foo.php?foo=bar&lang=fr&toto=titi&b=a => fr/foo.php?foo=bar&toto=titi&a=b
Run Code Online (Sandbox Code Playgroud)

这里唯一的问题是lang可能是部分或完整的url编码并且不会被检测到,但这是一种罕见的情况.我alos删除了对lang值只有2个字符的控制.我认为([^&]+)更好,它意味着所有角色,直到我匹配&.