【发布时间】:2013-09-02 10:37:29
【问题描述】:
我已经将所有需要的查询字符串重写为对 SEO 友好的 URL,例如
RewriteRule ^item_([0-9]+)/$ database.php?type=product&id=$1 [L]
RewriteRule ^post_([0-9]+)/$ articles.php?id=$1 [L]
... and so on
但我想删除任何其他查询字符串,例如 item_123/?foo=bar 或 database.php?foo=bar 或 post_123/?type =product&id=321 出于 SEO 和安全原因。
明显明显的放置解决方案
RewriteCond %{QUERY_STRING} (.+)
RewriteRule (.*) http://www.example.com/$1? [R=301,L]
在 .htaccess 的末尾处理之前没有处理过并被 [L] 标签停止的所有内容实际上破坏了原始 RewriteRule 并将 item_123/ 重定向到空的 数据库。 php 没有参数。
是否可以在不明确写下所有 %{REQUEST_URI}s 和 %{QUERY_STRING}s 对的异常的情况下删除所有查询字符串,但之前已经 mod_rewritten 的那些查询字符串除外?
编辑:
解决方案 A
# You do not need this whole block if you're running Apache v2.3.9+
RequestHeader set SOME-FANCY-NAME-FOR-THE-HEADER-AS-DESCRIBED-IN-THE-ABOVE-LINK 1 env=END
RewriteCond %{HTTP:SOME-FANCY-NAME-FOR-THE-HEADER-AS-DESCRIBED-IN-THE-ABOVE-LINK} =1 [NV]
RewriteRule .* - [L]
由于[END] 标志仅适用于 Apache v2.3.9+,因此我使用了a workaround which would emulate this behaviour。
# Replace [L,E=END:1] with [END] if running Apache v2.3.9+
RewriteCond %{THE_REQUEST} ^GET\ [^?]+$
RewriteRule ^item_([0-9]+)/$ database.php?type=product&id=$1 [L,E=END:1]
首先在 THE_REQUEST 中简单地限制任何 ? 将导致找不到 item_123/?foo=bar 模式的重复页面 (404)。 [L,E=END:1] 标志告诉 mod_rewrite 停止当前迭代并重复;下一次迭代将触发RewriteRule .* - [L] 并阻止它到达我们之后的潜在循环。 [END] 标志,如果支持,将立即停止它。
RewriteCond %{QUERY_STRING} type=product
RewriteCond %{QUERY_STRING} id=([0-9]+)
RewriteRule ^database\.php$ http://www.example.com/item_%1/? [R=301,L]
这还将重定向 (301) database.php?type=product&foo=bar&id=123 模式的潜在受损重复页面到正确的 URL,而不管查询中的乱码参数。一旦到达正确的 URL,它就会停在那里而不会导致循环和错误 500。
# If page is accessible without parameters
RewriteCond %{THE_REQUEST} ^GET\ [^?]+$
RewriteRule ^catalog/$ database.php [L,E=END:1]
RewriteCond %{THE_REQUEST} ^GET\ [^?]+\?
RewriteRule ^database\.php$ http://www.example.com/catalog/? [R=301,L]
如果页面可以在没有上述?type 和&type 等参数的情况下访问,但以database.php?foo=bar 或database.php? 的形式访问,它将被重定向(301) 到catalog/ 而没有查询字符串。同样,将找不到 catalog/?foo=bar 模式的页面 (404)。
# If page is not accessible without parameters
RewriteCond %{THE_REQUEST} ^GET\ [^?]+\?
RewriteRule ^database(\.php|/)?$ database.php [L,E=END:1]
如果页面在没有参数的情况下无法访问,我们可以强制停止重写(以避免稍后不必要的重定向,例如,如果我们将 anyotherfile.php 重写为 anyotherfile/)并让页面在知道之后发送 404 标头本身没有传递有效参数。
解决方案 A+B
accepted solution 中的代码本身是正确的,而我的版本扩展了重写以匹配许多其他格式错误的模式。
在上述所有代码之后从已接受的解决方案中添加代码将捕获(以前)未找到的 item_123/?foo=bar 和 catalog/?foo=bar 模式的链接,并将它们 (301) 重定向到正确的 URL item_123/ 和 @987654349 @ 没有查询字符串。这是有道理的,因为即使用户遵循由某些 RSS 聚合器等修改的链接,用户也会到达他想要的地方。将%{QUERY_STRING} (.+) 更改为%{THE_REQUEST} ^GET\ [.?]+\? 以及在上述代码中使用%{THE_REQUEST} ^GET\ [^?]+$ 而不是%{QUERY_STRING} ^$ 也会删除尾随问号 - item_123/? - 否则会被忽略并算作重复页面。
RewriteCond %{THE_REQUEST} ^GET\ [^?]+\?
RewriteRule (.*) http://www.example.com/$1? [R=301,L]
【问题讨论】:
-
注意通配符重写(您有问题的最后一条规则),并注意以下几点:Mod_Rewrite unexpected behavior L flag
标签: php .htaccess mod-rewrite query-string