Mod Rewrite+QSA:重写目标和querystring中的querystring参数相同-是否可能强制使用目标



我们有以下重写规则:

RewriteRule ^([A-Za-z0-9_]+)$ index.php?rewrite=$1 [L,QSA]

我们想知道是否有办法?rewrite=$1是否优先于通过请求uri中的查询字符串传递的值?

因为目前的情况是,由于QSA标志(我们确实需要btw),如果命中以下url:

http://www.domain.com/this_rewrite_will_match_the_above_rule?rewrite=some_value

PHP中$_GET['write']的值将是some_value,而不是this_write_will_match_The_above规则

在我们开始修改重写并添加RewriteCond以匹配查询字符串之前,等等……我们希望有一个标志可以设置,以便目标url(在这种情况下为index.php?rewrite=$1)优先于传递的查询字符串值。

希望这是有道理的。

谢谢。

有点粗糙的

RewriteRule ^([A-Za-z0-9_]+)$ index.php?%{QUERY_STRING}&rewrite=$1 [L]

这是因为在php中,第二个rewrite=...会覆盖第一个。

我已经多次强烈地搜索了一些机制来覆盖Apache重写中的单个查询字符串参数,但看起来没有这样做的选择,即使是最新的Apache版本(在撰写本文时为2.4.3)。

但是,还有一种替代方法可以利用这样一个事实,即PHP查询字符串解析器只返回多个相同查询字符串参数中的最后一个。

示例:

http://www.domain.com/index.php?id=123&id=456

这将返回$_GET:中的以下单个(!)条目

array(1) {
["id"]=>
string(3) "456"
}

因此,只需在现有查询字符串的末尾添加任何重写参数(而无需在查询字符串中删除它们),就可以解决问题。重复参数的最后一次出现是使其进入$_GET数组的参数。

不幸的是,QSA开关不适合这种技术,因为它总是将原始参数附加到新查询字符串的末尾。没有一个开关可以预处理旧参数。因此,您必须使用RewriteCond来捕获并准备原始查询字符串,而不是使用QSA:

RewriteCond  %{QUERY_STRING}  ^(.*)$
RewriteRule ^([A-Za-z0-9_]+)$ index.php?%1&rewrite=$1 [L]

RewriteCond的唯一功能是捕获%1中的查询字符串。条件的正则表达式(.*)始终匹配,因此始终执行以下RewriteRule。

使用此技术,您的上述测试用例将重写为…

http://www.domain.com/index.php?rewrite=some_value&rewrite=this_rewrite_will_match_the_above_rule

它将由PHP查询字符串解析器解释为

$_GET["id"] => "this_rewrite_will_match_the_above_rule"

这就是你想要的。

请注意,只有当您从PHP的$_GET数组中获取查询字符串值时,这才会起作用。如果您自己解析$_SERVER["QUERY_STRING"]的内容或使用任何其他编程语言,则它不一定有效。

我选择创建自己的答案,因为它比Jpsy和Gerben提供的示例稍微干净一些。

信用是应该信用的地方,他们的建议是我来到这里的原因,我只扩展了他们:

因此,我们的最终解决方案包括2条规则。

# check if querystring is not empty (this is the addition vs other answers)
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9_]+)$ index.php?%{QUERY_STRING}&rewrite=$1 [L]

如果上述查询字符串失败(主要是查询字符串为空),则应用此规则。

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9_]+)$ index.php?rewrite=$1 [L]

我选择这种双重规则设置的原因是,如果查询字符串为空,避免php服务器变量被"?&rewrite=…"污染。

感谢jpsy和gerben的帮助。

我使用了以下说明:

RewriteRule ([^?]*)?(.*) $1?$2 [N]                          (1)
RewriteCond %{QUERY_STRING} (.*?)&?(rewrite=[^&]+)&?(.*)      
RewriteRule ^(.*)$ $1?%1&%3 [N]                               (2)
RewriteRule ^(.*)$ $1?domain=newValue [L,QSA]                 (3)

技巧是由前两个规则中的[N]标志完成的,它导致重写引擎来重新处理输出。

规则(1)简单地按原样重写url。我需要它,因为我使用mod_rewrite togheter和mod_proxy_ajp,并且在第一次迭代中,查询字符串没有从url中分离出来。执行第一行后,url保持不变,但引擎将从查询字符串中分离路径。

规则(2)迭代并从查询字符串中删除所有出现的参数"rewrite"。

规则(3)设置参数的新值,并附加从规则(2)所做的替换中幸存下来的查询字符串。

最新更新