我的网站软件用URL中的“+”字符replace空格字符,正确的链接看起来像“ http://www.schirmacher.de/display/INFO/How+to+reattach+a+disk+to+XenServer ”例如。
有些网站链接到这篇文章,但不知何故,他们的embedded式编辑器无法处理编码,所以我在httpd日志文件中看到的其实是
GET /display/INFO/How%2525252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
这当然会导致404错误。 看来“+”字符被编码为“%2b”,然后“%”字符被编码为“%25” – 几次。
由于有很多这样的引用来自不同网站的不同网页,我想重写url,以便访客得到正确的页面。
这是我的尝试不起作用:
RewriteRule ^(.*)%25(.*)$ $1%$2 [R=301]
它应该做的是:将%25string之前的所有内容以及所有之后的所有内容与中间的'%'连接起来,然后redirect。
用规则应该重写的示例inputURL
/display/INFO/How%25252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
其次是redirect,然后重写
/display/INFO/How%252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
并再次
/display/INFO/How%2bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
等等。 最后,我应该离开了很多redirect之后
/display/INFO/How%2bto%2breattach%2ba%2bdisk%2bto%2bXenServer
这是一个有效的url等同于/ display / INFO / How + to +重新附加+ a +磁盘+到+ XenServer。
我的问题是,expression式根本不匹配,所以它甚至不会replace%25的单个匹配项。
我知道redirect的数量是有限制的,我真的应该使用[N]标志,但是我甚至没有正确的第一步。
本·李:谢谢你的详细解答。 我现在在这个问题上花了几个小时。 这是我发现的:
在mod_rewrite看到之前,url中的任何'%25'string都被转换为'%'。 所以RewriteRule ^(。 )%25(。 )$在url中不匹配'%25',它实际上匹配'%2525'。
反斜杠的存在并没有什么不同。 看来'%'符号在我的情况下不被解释为反向引用,也许是因为之前没有RewriteCond语句。 但是可以肯定的是,使用它可能会更好。
具有[L,R = 301]的行不正确。 它会尝试重新定向每个%2b的匹配,但是有一个允许的redirect的限制,如果有更多的redirect将会失败。
这里是我使用的mod_rewrite行:
RewriteRule ^(.*)\%25(.*\%25.*)$ $1%$2 [N] RewriteRule ^(.*)\%25(.*)$ $1%$2 [R=301,L] RewriteRule ^(.*)\%2b(.*\%2b.*)$ $1+$2 [N] RewriteRule ^(.*)\%2b(.*)$ $1+$2 [R=301,L]
第三行将用“+”字符replace除了一个%2b序列以外的所有序列。 当只剩下一个%2b序列时,第四行将匹配,强制redirect。
第一行和第二行基本上是相同的,但有一个%25的顺序。 每个可能的字符序列都有一个[R]标志的规则是必要的,因为我也使用mod_proxy / mod_jk,redirect将确保生成的url再次被送到每个模块。 否则,httpd会尝试从磁盘获取URL,这在我的情况下会失败。
这是你原来的规则,添加[L]表示“last”:
RewriteRule ^(.*)%25(.*)$ $1%$2 [L,R=301]
之后,这里有一些问题。 首先, RewriteRule模式中的百分号具有特殊含义; 它们表示对RewriteCond的返回引用的开始。 你可以避开它们(使用反斜杠):
RewriteRule ^(.*)\%25(.*)$ $1%$2 [L,R=301]
其次,当你插入%到replace,它不会继续作为一个Uri编码片的一部分。 它转化为字面上的百分号。 在你接收到的原始url中,第一个%25"被转换成了一个字面百分号,所以上面的规则将导致字面值为%25或文字%2b ,而不是parsing为%或+ 。所以你必须自己手动解决这些问题。
RewriteRule ^(.*)\%25(.*)$ $1%$2 RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]
最后,因为你在初始%之后不仅仅有一个25 ,而且可能有很多,所以用[N]来表示“下一个”。 这基本上意味着“从头开始过程,但使用我的新url作为input”。 所以这将处理百分之二25后的任何数字:
RewriteRule ^(.*)\%25(.*)$ $1%$2 [N] RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]
注意:如果你在常规的apacheconfiguration中设置你的规则,这应该工作。 如果您将其设置为.htaccess ,则在对照正则expression式检查的string中将省略前导斜杠,在这种情况下,您必须将它们添加回自己:
RewriteRule ^(.*)\%25(.*)$ /$1%$2 [N] RewriteRule ^(.*)\%2b(.*)$ /$1+$2 [L,R=301]
更新 :我没有能力现在testing,但看看文档,我只是看到一个选项NE “不可逃脱”,使得百分比在结果中作为常规编码标记。 如果我理解正确,那就意味着规则可以简化为:
RewriteRule ^(.*)\%25(.*)$ $1%$2 [NE,N,L,R=301]
但是,这还没有经过testing,我从来没有真正使用NE标志,所以我可能会误解它。 如果你testing这个,并发现它的工作,让我知道,我会删除这个更新,只是修复上述的答案,包括这个更简单的版本。