我有所有查询字符串,我需要将其重写为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 /?类型搜索引擎优化和安全原因导致产品& id = 321 。
显而易见的放置解决方案
RewriteCond %{QUERY_STRING} (.+)
RewriteRule (.*) http://www.example.com/$1? [R=301,L]
<。>在.htaccess的末尾处理之前没有bean处理过的所有事情,并且[L]标签停止实际上会破坏原始的RewriteRule并将 item_123 / 重定向到空的数据库。 php ,没有参数。
是否可以删除除早先mod_rewritten之外的所有查询字符串而不明确写下所有%{REQUEST_URI}和%{QUERY_STRING}对的异常?
# 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]
这也将database.php?type=product&foo=bar&id=123
模式的可能受损的重复页面重定向(301)到正确的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)到{{1}没有查询字符串。同样,将找不到catalog/
模式的页面(404)。
catalog/?foo=bar
如果在没有参数的情况下无法访问页面,我们可以强制停止重写(以避免以后不必要的重定向,例如我们将# If page is not accessible without parameters
RewriteCond %{THE_REQUEST} ^GET\ [^?]+\?
RewriteRule ^database(\.php|/)?$ database.php [L,E=END:1]
重写为anyotherfile.php
)并使页面本身发送404标头一旦它知道没有传递有效参数。
来自accepted solution的代码本身是正确的,而我的版本扩展了重写以匹配许多其他格式不正确的模式。
在完成上述所有代码后,从接受的解决方案中添加代码将捕获anyotherfile/
和item_123/?foo=bar
模式的(以前)未找到的链接,并将它们(301)重定向到正确的URL {{ 1}}和catalog/?foo=bar
没有查询字符串。这是有道理的,因为即使用户遵循由某些RSS聚合器等修改的链接,用户也会到达他想要的位置。在上述代码中将item_123/
更改为catalog/
并使用%{QUERY_STRING} (.+)
代替%{THE_REQUEST} ^GET\ [.?]+\?
也会删除跟踪问号 - %{THE_REQUEST} ^GET\ [^?]+$
- 否则会被忽略,如果加入,则计为重复页面。
%{QUERY_STRING} ^$
答案 0 :(得分:2)
L标志不会停止。如果你更改了URL(你做了),它会重新注入。因此,对于您所做的每个内部重定向(重写),最后一个条件都可以,然后触发最后一次重写:
RewriteCond %{QUERY_STRING} (.+)
RewriteRule (.*) http://www.example.com/$1? [R=301,L]
由于这个删除了查询字符串(以?
结尾,没有QSA
标志),因此您将使用不带参数的php脚本结束:
rewrite #1/1: item_5/ -> database.php?type=product&id=5
L triggered, because URL changed, re-inject:
rewrite #1/2: database.php?type=product&id=5 -> http://www.example.com/database.php?
R triggered, exiting
rewrite #2/1: http://www.example.com/database.php? -
no rule matches, use as-is
相反,您需要在最后放置一个条件,以便不重定向.php文件:
RewriteCond %{QUERY_STRING} (.+)
RewriteCond %{REQUEST_URI} !^/[a-z]+\.php$
RewriteRule (.*) http://www.example.com/$1? [R=301,L]
或者如果你有一个更现代的apache服务器版本,只需使用END
标志:
RewriteRule ^item_([0-9]+)/$ database.php?type=product&id=$1 [END]
RewriteRule ^post_([0-9]+)/$ articles.php?id=$1 [END]
... and so on
答案 1 :(得分:0)
我不知道这是否有帮助,但我处理的方法是将不存在的文件发送到特定的php文件(rewrite.php)
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^.*$ ./rewrite.php
这让我可以轻松处理我遇到的每一个案例
答案 2 :(得分:0)
您可以使用以下方法来避免这种情况:
RewriteRule ^item_([0-9]+)/.*$ abc.php?type=product&id=$1 [L]
我添加.*
以匹配斜线后的任何内容,但它仍然是重定向的有效模式。