Apache mod_rewrite 模块处理 query string的做法

1. 匹配所针对的URL部分

mod_rewrite的RewriteRule语法为:

RewriteRule Pattern Substitution [flags]

其中在Virtual Host中Pattern只匹配host和port之后的部分,query string也不属于匹配范围,例如,请求URL为http://www.mydomain.com:8080/myaction?param=123,那么pattern只针对/myaction这部分内容。

Substitution 用来替换成功匹配的URL;Flags是一些控制匹配的标志,标志之间用逗号隔开,例如R表示跳转(Redirect),L表示规则终止(Last)。

例如, 有如下的匹配规则:
RewriteRule ^/$ /default/myaction [R,L]

若请求URL为http://www.mydomain.com:8080/myaction?param=123,那么经过mod_rewrite会跳转(通过标志R)到http://www.mydomain.com:8080/default/myaction?param=123。注意,这里的query string完好无损。



2. 附加查询字符串标志(QSA)

如果现在需要在跳转的URL中添加一个查询参数userid=1,该怎么办?

首先看规则这样写行不行:

RewriteRule ^/$ /default/myaction?userid=1 [R,L]

答案是:不可以。如果这样写的话,跳转的URL会变成http://www.mydomain.com:8080/default/myaction?userid=1,注意这里把原始的查询参数param=123给丢掉了。

正确的写法是使用QSA标志:

RewriteRule ^/$ /default/myaction?userid=1 [QSA,R,L]

这样QSA标志表示在用户添加的查询参数后附加原有的查询参数,即跳转的URL为:http://www.mydomain.com:8080/default/myaction?userid=1&param=123。


3. 一个完整的例子

问题:如果用户输入的URL为http://www.mydomain.com:8080?phone=123,那么自动跳转到http://www.mydomain.com:8080/default/myaction_phone?company=1&phone=123;如果用户输入的URL为http://www.mydomain.com:8080,那么自动跳转到http://www.mydomain.com:8080/default/myaction?company=1。这里第一个跳转URL执行操作是myaction_phone,第二个跳转URL执行的操作是myaction。

答案:在Apache的虚拟主机配置中,可以这样写:

RewriteEngine on
RewriteCond %{QUERY_STRING} ^phone
RewriteRule ^/$ /default/myaction_phone?company=1 [QSA,R,L]
RewriteRule ^/$ /default/myaction?company=1 [R,L]

在这个配置中,RewriteCond只适用带QSA的第一条规则,因为这是规则链中的第一条也是最后一条规则(通过L标志),也就是说,只要查询字符串以phone开头,就应用第一条规则如果用户请求的URL不满足RewriteCond的条件,就使用第二条规则。


4. 总结
下面一段引用自Apache mod_rewrite文档(http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule)中的一段话,这段话基本上概括了mod_rewrite如何处理query string的问题:

Modifying the Query String
By default, the query string is passed through unchanged. You can, however, create URLs in the substitution string containing a query string part. Simply use a question mark inside the substitution string to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine new and old query strings, use the [QSA] flag.


你可能感兴趣的:(apache,String,url,query,文档,redirect)