Apache – RewriteRule指令

平常开发里,重载应该不会少,今天又仔细看了一遍apache文档,关于RewriteRule这一节,下面是我的总结。

首先RewriteRule的语法是这样的:

RewriteRule Pattern Substitution [flags]

1. Pattern会匹配到什么?

在服务器级别(<VirtualHost>)的配置中,会匹配整个url,包括最前面的/,所以写rule时,应该^/
而在目录级别(<Directory>或.htaccess)的配置中, 会除去url里当前目录的前缀,并且不会匹配前面的/.

比如/documentroot/html/下有.htaccess

RewriteRule ^test.php test2.php
访问
GET /html/test.php
会匹配到test.php
GET /html/a/test.php
会匹配到a/test.php

但是要注意的是,此时基准目录是html,也就是说上面的匹配不会重载到html/a/test2.php,目标还是目录html下的test.php,如果想重载到目录a下的test.php,那么使用

RewriteBase /html/a

还有一点是, pattern匹配只会匹配到REQUEST_URI为止,换句话说QUERY_STRING是不会被匹配到的,如果想要用QUERY_STRING做判断使用

RewriteCond %{QUERY_STRING}

2. Substitution会有什么值?

常见的可能是filesystem_path或url_path( 即相对于DOCUMENT_ROOT ),比如/www/a.hml, 那mod_rewrite是怎么判断是前者还是后者,因为从表面看两种情况都有可能,规则是这样,如果/www目录( 即根目录下www文件夹 )存在,该参数会被当做文件目录,否则则会被当做url_path,或者/www不存在但是有Alias指令存在,那么可以使用 [PT] 标志让他强制当做目录,例如 (服务器级别配置下)

Alias /abc /xyz (xyz为真实目录)
RewriteRule ^/def/test.php /abc/test.php [PT]

关于query_string,一般来说query_string会原封不动的传入,例如(服务器级别配置下)

RewriteRule ^/arg/([0-9]+)/?$ test.php
访问
GET /arg/1?name=1 
相当于
GET /test.php?name=1

如果想修改query_string,那么只需要在Substitution后面跟上?  例如:

RewriteRule ^arg/([0-9]+)/?$ test.php?foo=bar
那么情况就变了,访问
GET /arg/1?name=1 
相当于
GET /test.php?foo=bar

如果想合并新的和旧的query_string,那么加上标志 [QSA] 即可

RewriteRule ^arg/([0-9]+)/?$ test.php?foo=bar [QSA]

RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^a/([0-9]+)/?$ test.php?a=1&%1

RewriteRule ^a/([0-9]+)/?$ test.php?a=1&%{QUERY_STRING}
总结有限,如有错误,请指正。

Leave a comment

电子邮件地址不会被公开。 必填项已用*标注