本文是mod_rewrite参考文档的补充材料。阐述在实际应用中如何解决网管所面临的基于URL的典型问题,并详细描述了如何配置URL重写规则集以解决这些问题。
mod_alias和mod_userdir的情况下要增加[PT]标志,或者为了适应目录级(.htaccess)的配置而将针对服务器级的规则集进行重写。对一个特定的规则集应该先透彻理解然后再考虑应用,这样才能避免出现问题。/u/user替换/~user,并修正了/u/user所遗漏的后缀斜杠。
RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R] RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]
对运行在非80端口的站点
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]
对运行在80端口的站点
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]
DocumentRootDocumentRoot直接对应于URL"/",但是它常常不是处于最高的一级。比如,你希望访问者在进入网站时首先进入/about/目录。可以使用下面给出的规则集。/"重定向到"/about/"即可:
RewriteEngine on RewriteRule ^/$ /about/ [R]
也可以使用RedirectMatch指令解决问题:
RedirectMatch ^/$ http://example.com/e/www/
/~quux/foo/index.html页面中的image.gif的请求将变成对/~quux/image.gif的请求!所以,应该这样写:
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo$ foo/ [R]
又懒又疯狂的做法是把这些写入其宿主目录中的顶级.htaccess中:
RewriteEngine on
RewriteBase /~quux/
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]
但是这样一来会增加处理上的开销。
/~user/anypath"到"http://newserver/~user/anypath":
RewriteEngine on RewriteRule ^/~(.+) http://newserver/~$1 [R,L]
RewriteEngine on
# 首先尝试在 dir1 中寻找,找到即停
RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir1/$1 [L]
# 然后尝试在 dir2 中寻找,找到即停
RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir2/$1 [L]
# 再找不到就继续寻找其他的 Alias 或 ScriptAlias 目录
RewriteRule ^(.+) - [PT]
/foo/S=java/bar/"的URL会被解析为"/foo/bar/",而环境变量STATUS则被设置为"java"。
RewriteEngine on RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]
www.username.host.domain.com的主页,但不在此机器上建虚拟主机,而是仅用在此机器上增加一个DNS A记录的方法实现。http://www.username.host.com/anypath重写为/home/username/anypath
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2
ourdomain.com的外来访问者的请求,重定向其用户主目录URL到另一个web服务器www.somewhere.com,有时这种做法也会用在虚拟主机的配置段中。
RewriteEngine on
RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$
RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]
#'会被转义为'%23'。This, in turn, breaks the redirection.RewriteRule指令中使用[NE]标志(不转义)。mod_rewrite来实现呢?TIME_xxx的变量可以用在重写条件中,联合使用词典模式的"<STRING", "=STRING", ">STRING"比较,就可以实现依赖于时间的重写:
RewriteEngine on
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule ^foo\.html$ foo.day.html
RewriteRule ^foo\.html$ foo.night.html
此例使foo.html在07:00-19:00时间内指向foo.day.html,而在其余时间指向foo.night.html,对主页是一个不错的功能...
document.YYYY文件为document.XXXX后(比如.html→.phtml),如何保持URL的向前兼容(仍然虚拟地存在)?
# 将document.html重写为document.phtml的向后兼容的规则集
# 当且仅当document.phtml存在且document.html不存在的时候
RewriteEngine on
RewriteBase /~quux/
# 剪切并记住basename
RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes]
# 如果存在的话就重写为document.phtml
RewriteCond %{REQUEST_FILENAME}.phtml -f
RewriteRule ^(.*)$ $1.phtml [S=1]
# 否则返回先前的basename
RewriteCond %{ENV:WasHTML} ^yes$
RewriteRule ^(.*)$ $1.html
foo.html改名为bar.html,需要对老的URL向后兼容,即让用户仍然可以使用老的URL,而感觉不到文件被改名了。RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ bar.html
foo.html改名为bar.html,需要对老的URL向后兼容,但是要让用户得到文件被改名的暗示,即浏览器的地址栏中显示的是新的URL。RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ bar.html [R]
foo.html为动态的foo.cgi,而不为浏览器/用户所察觉。/~quux/foo.html的请求会执行/~quux/foo.cgi 。
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ foo.cgi [T=application/x-httpd-cgi]
/robots.txt文件可以包含若干"Robot排除协议"行,但不足以阻止此类Robot。/~quux/foo/arc/(对一个很深的目录区域进行列表可能会使服务器产生很大的负载)的访问。还必须确保仅阻止特定的Robot,也就是说,仅仅阻止Robot访问主机是不够的(这样会同时阻止用户访问该主机)。为此,就需要对HTTP头的User-Agent信息作匹配。
RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$
RewriteRule ^/~quux/foo/arc/.+ - [F]
http://www.quux-corp.de/~quux/有一些内嵌GIF图片的页面,这些图片很好,所以就有人盗链到他们自己的页面中了。由于这样徒然增加了我们服务器的流量,因此,我们不愿意这种事情发生。
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
RewriteRule .*\.gif$ - [F]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$
RewriteRule ^inlined-in-foo\.gif$ - [F]
mod_rewrite位于mod_proxy之后!使它在mod_proxy之前被调用。然后,使用如下方法拒绝某个主机:
RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
使用如下方法拒绝user@host-dependent用户:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
mod_rewrite解决的FOO/BAR/QUUX/之类的问题?RewriteMap功能相同的外部RewriteMap程序,一旦它在Apache启动时被执行,则从STDIN接收被请求的URL ,并将处理过(通常是重写过的)的URL(以相同顺序)在STDOUT输出。
RewriteEngine on
RewriteMap quux-map prg:/path/to/map.quux.pl
RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1}
#!/path/to/perl
# 禁止使用会导致Apache陷入死循环的I/O缓冲
$| = 1;
# 从stdin读取URL(每行一个),并在stdout输出替换URL
while (<>) {
s|^foo/|bar/|;
print $_;
}
/~quux/foo/...重写为/~quux/bar/...而已。但事实上,可以把它修改成任何你想要的输出。但是要注意,虽然一般用户都可以使用,可是只有系统管理员才可以定义这样的映射。