首页 > 解决方案 > htaccess RewriteRule:在第一个参数之后省略所有的问题

问题描述

目标:想要重写所有类型的 URL

https://www.example.com/page/1234/?/blog/foo/bar/

https://www.example.com/page/1234/

.htaccess我尝试了很多变化

RewriteEngine On
RewriteBase /
RewriteRule ^page/(\d+)/(.*)$  /page/$1 [R=301,L] 

使用.htaccess测试仪,我发现至少匹配模式是有效的。

我希望重写后不会包含任何内容$1,但它确实包含,并显示完整的原始 URL。

我错过了什么?

标签: apache.htaccessmod-rewrite

解决方案


https://www.mypage.com/page/1234/?/blog/foo/bar/

第一个之后的所有内容都是 URL?查询字符串部分。默认情况下,Apache 将请求中的查询字符串原封不动地传递给目标 URL(除非您自己在RewriteRule 替换上创建新的查询字符串)。这解释了为什么您在目标 URL 上看到相同的查询字符串,而似乎没有对其进行任何操作。

顺便说一句,该RewriteRule 模式仅与 URL 路径匹配——这特别排除了查询字符串。要匹配 mod_rewrite 中的查询字符串,您需要一个额外的条件来检查QUERY_STRING服务器变量。

在 Apache 2.4+ 上,您可以使用QSD(Query String Discard) 标志从目标 URL 中删除查询字符串。或者,在替换上指定一个空查询字符串- 通过包含尾随?(其?本身不会出现在结果 URL 上)。

例如(在 Apache 2.4 上):

RewriteCond %{QUERY_STRING} .
RewriteRule ^page/(\d+)/  /page/$1/ [QSD,R=301,L]

RewriteCond指令检查是否存在查询字符串,这是防止重定向循环所必需的。

图案(.*)$上的尾随是多余的。RewriteRule

您省略了替换末尾的斜杠(位于示例 URL 中)。这也可以防止重定向循环,但如前所述,这与您的示例不同。(或者,您可以在捕获的反向引用中包含斜线。)

如果您仍在使用 Apache 2.2,那么您需要包含尾随?而不是QSD标志。例如:

RewriteRule ^page/(\d+)/  /page/$1/? [R=301,L]

您需要在测试前清除浏览器缓存,因为 301(永久)重定向会被浏览器永久缓存。出于这个原因,首先使用 302(临时)重定向进行测试通常更容易。


推荐阅读