我们有一个带有动态URL方案的PHP应用程序,它要求字符是百分比编码的,甚至是"无保留字符“,比如圆括号或不需要编码的aphostrophes。应用程序认为以“错误”方式编码的URL被规范化,然后重定向到“正确”编码。
但是Google和其他用户代理会对百分比进行规范化编码/解码,这意味着当Googlebot请求页面时,它会请求“错误”URL,当它返回到“正确”URL时,Googlebot将拒绝遵循重定向,并拒绝对页面进行索引。
是的,这是我们这边的一个窃听器。HTTP规范要求服务器以相同的方式对待百分比编码和非百分比编码的非保留字符。但是,现在解决应用程序代码中的问题并不简单,所以我希望通过使用Apache重写规则来避免代码更改,这将确保从应用程序的角度“正确地”对URL进行编码,这意味着apopstrophes、括号等都是全部编码的,空格被编码为+,而不是%20。
这里有一个例子,我想重写第一个表单,并以第二个表单结束:
这是另一个:
这是另一个:
如果应用程序只看到这些URL的第二种形式,那么它将不会发送任何重定向,Google将能够索引页面。
我是一个重写规则的新手,从我对国防部-重写文档的阅读中可以清楚地看到,mod_rewrite做了一些自动编码/解码,这可能会帮助或伤害我想要做的事情,尽管还不确定。
对于重写规则以处理上述情况,有什么建议吗?我对每个特殊字符都有一个规则,因为它们不多,但是一个规则(如果可能的话)将是理想的。
发布于 2010-09-28 00:30:33
这个解决方案实际上可能相当简单,但由于使用了标志,它只能在Apache2.2中工作,而且在以后的版本中也是如此。我不确定它是否正确地处理了每一种情况(诚然,我对它不涉及比这更多的工作有点怀疑),但我被引导相信它应该通过源代码来处理。
还请记住,REQUEST_URI的值不是由mod_rewrite转换更新的,所以如果应用程序依赖于该值来确定请求的URL,那么您所做的更改无论如何都是不可见的。
好消息是,这可以在.htaccess中完成,所以您可以选择保留主配置,如果这样做对您更好的话。
RewriteEngine On
# Make sure this is only done once to avoid escaping the escapes...
RewriteCond %{ENV:REDIRECT_STATUS} ^$
# Check if we have anything to bother escaping (likely unnecessary...)
RewriteCond $0 [^\w]+
# Rewrite the entire URL by escaping the backreference
RewriteRule ^.*$ $0 [B]那么,为什么需要使用B标志而不是让mod_rewrite自动逃离重写的URL呢?当mod_rewrite自动转义URL时,它使用ap_escape_uri (显然由于某种原因它已被转换为ap_os_escape_path宏),这是一个转义有限的字符子集的函数。然而,B标志使用了一个名为escape_uri的内部模块函数,该函数是以PHP的urlencode函数为模型的。
模块中escape_uri的实现表明字母数字字符和下划线被保留为- is,空格被转换为+,其他一切都转换为其转义等价物。这似乎是你想要的行为,所以它大概会起作用。
如果没有,您可以选择设置一个外部程序RewriteMap,该程序可以将传入的URL操作为正确的格式。不过,这需要操作Apache配置,而且一个变节脚本可能会对整个服务器造成问题,所以如果可以避免,我认为它不是一个理想的解决方案。
发布于 2010-09-27 18:07:25
mod_rewrite不是做这种工作的最佳工具。因为使用mod_rewrite,一次只能替换固定数量的事件。但有可能:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)
RewriteRule ^ /%1\%29%2 [R=301,NE]这将一次替换一个%20、'、(或),并以301重定向进行响应。因此,如果URL路径包含需要替换的10个字符,则需要进行10次重定向。
由于这可能不是最好的解决方案,所以除了最后一次使用标志的内部替换之外,还有最后一次用重定向进行外部替换是可能的:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*)%20(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*%20[^?\ ]*)
RewriteRule ^ /%1+%4 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)[?\ ]
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*'[^?\ ]*)
RewriteRule ^ /%1\%27%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)[?\ ]
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*\([^?\ ]*)
RewriteRule ^ /%1\%28%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)[?\ ]
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*\)[^?\ ]*)
RewriteRule ^ /%1\%29%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)[?\ ]
RewriteRule ^ /%1\%29%2 [R=301,NE]但是使用N标志可能是危险的,因为它不会增加内部递归计数器,因此很容易导致无限递归。
https://stackoverflow.com/questions/3791548
复制相似问题