Apache Rewrite规则(内部重定向、外部重定向)

前阵子某天,一同事让我帮忙看一下某内部服务器的域名跳转的配置,本来这两年好像没做Web服务器方面东西了,不过鉴于曾经在互联网行业工作过,还是略懂Apache配置,也想顺便玩一下。最后的配置还是比价简单的,也实现了他所需的功能。今天有点空闲时间,想写篇博客总结一些apache rewrite的配置语法和实例(源于网络资料),以便今后快速查阅。

我最后其实就在httpd.conf文件写了如下几行配置就将域名中以“otc-team”开头的URL重定向为“http://otcteam.mycompany.com/”下面的对应URL。

1. 一些基础知识的介绍:
The mod_rewrite module uses a rule-based rewriting engine, based on a PCRE regular-expression parser, to rewrite requested URLs on the fly. By default, mod_rewrite maps a URL to a filesystem path. However, it can also be used to redirect one URL to another URL, or to invoke an internal proxy fetch.
mod_rewrite provides a flexible and powerful way to manipulate URLs using an unlimited number of rules. Each rule can have an unlimited number of attached rule conditions, to allow you to rewrite URL based on server variables, environment variables, HTTP headers, or time stamps.
mod_rewrite operates on the full URL path, including the path-info section. A rewrite rule can be invoked in httpd.conf or in .htaccess. The path generated by a rewrite rule can include a query string, or can lead to internal sub-processing, external request redirection, or internal proxy throughput.
简单解释一下内部重定向和外部重定向吧。内部重定向,是指域名并不发生变化,只是将某个URL映射到了文件系统中的另一个路径。外部重定向,是指URL已经法发生变化(在浏览器中显示看到的域名也跟着变化了),从一个URL映射到了另一个URL(可以是不同主机的,当然也可以是同一主机上的)。
PCRE(Perl Compatible Regular Expressions)是与Perl5.x兼容的正则表达式,使用这种正则表达式的著名软件项目有Apache、PHP、KDE、Safari等。

重写规则的作用范围,有如下三种:
1) 可以使用在Apache主配置文件httpd.conf中
2) 可以使用在httpd.conf里定义的虚拟主机配置中
3) 可以使用在基本目录的跨越配置文件.htaccess中
首先,apache在编译时将mod_rewrite编译为模块,然后在Apache的配置文件中加载它:
LoadModule rewrite_module modules/mod_rewrite.so
其次,这三种方式,都需要在写规则前,用“RewriteEngine on”指令来打开rewrite功能。
假如你对你的的网站内容所在的服务器没有管理员权限,或者你的网站放在ISP的服务器上托管等等条件下,你无法改写主配置文件,然而你可以对你的WEB站点内容所在的目录有写权限,则你可以设置自己的.htaccess文件。 (本博客站点就有设置.htaccess文件做rewrite。)对文件.htaccess所作的任何改动不需要重启动Apache. 不过,值得注意的是,需要确定主配置文件中对你的网站所在的目录定义了下面的内容:
Options Indexes FollowSymLinks
AllowOverride all
否则你的.htaccess文件配置不会工作。

2. Apache mod_rewrite规则重写的标志一览

1) R[=code](force redirect) 强制外部重定向
强制在替代字符串加上http://thishost[:thisport]/前缀重定向到外部的URL.如果code不指定,将用缺省的302 HTTP状态码。
2) F(force URL to be forbidden)禁用URL,返回403HTTP状态码。
3) G(force URL to be gone) 强制URL为GONE,返回410HTTP状态码。
4) P(force proxy) 强制使用代理转发。
5) L(last rule) 表明当前规则是最后一条规则,停止分析以后规则的重写。
6) N(next round) 重新从第一条规则开始运行重写过程。
7) C(chained with next rule) 与下一条规则关联
如果规则匹配则正常处理,该标志无效,如果不匹配,那么下面所有关联的规则都跳过。
8.) T=MIME-type(force MIME type) 强制MIME类型
9) NS (used only if no internal sub-request) 只用于不是内部子请求
10) NC(no case) 不区分大小写
11) QSA(query string append) 追加请求字符串
12) NE(no URI escaping of output) 不在输出转义特殊字符
例如:RewriteRule /foo/(.*) /bar?arg=P1%3d$1 [R,NE] #将能正确的将/foo/zoo转换成/bar?arg=P1=zoo
13) PT(pass through to next handler) 传递给下一个处理
例如:
RewriteRule ^/abc(.*) /def$1 [PT] # 将会交给/def规则处理
Alias /def /ghi
14) S=num(skip next rule(s)) 跳过num条规则
15) E=VAR:VAL(set environment variable) 设置环境变量

另外,P是代理模式转发,必须用url全称,并且要保证modProxy打开,也就是下面httpd.conf中的如下两个指令:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
如果对应proxy模块没加载,则会出现403禁止页面。

3. 一些有用的实际rewrite例子
例1.下面是在一个虚拟主机里定义的规则。功能是把client请求的主机前缀不是www.smilejay.cn和173.192.169.119都跳转到主机前缀为http://www.smilejay.cn,避免相同内容的网页有多个指向的域名,如http://smilejay.cn

例2. 将输入 en.smilejay.cn 的域名时跳转到www.smilejay.cn

例3. 赛卡软件近期更换了域名,新域名为www.sicasoft.com, 更加简短好记。这时需要将原来的域名ss.kiya.cn, 以及论坛所在地址ss.kiya.cn/bbs/定向到新的域名,以便用户可以找到,并且使原来的论坛 URL 继续有效而不出现 404 未找到,比如原来的http://ss.kiya.cn/bbs/tread-60.html, 让它在新的域名下继续有效,点击后转发到http://bbs.sicasoft.com/tread-60.html,而其他网页,如原先的http://ss.kiya.cn/purchase不会到二级域名bbs.sicasoft.com/purchase上,而是到www.sicasoft.com/purchase
按照这样的要求重定向规则应该这样写:

例4: 同时达到下面两个要求:
1.用http://www.zzz.com/xxx.php 来访问 http://www.zzz.com/xxx/
2.用http://yyy.zzz.com 来访问 http://www.zzz.com/user.php?username=yyy 的功能

例5:实现如下URL的rewrite:
/type*.html 被重定向为 /type.php?typeid=*
/type*page*.html 被重定向为 /type.php?typeid=*&page=*

例6.使用Apache的URL Rewrite配置多用户虚拟服务器
要实现这个功能,首先要在DNS服务器上打开域名的泛域名解析(自己做或者找域名服务商做)。比如,我就把 *.kiya.us和 *.kiya.cn全部解析到了我的IP地址70.40.213.183上。然后,看一下我的Apache中关于*.kiya.us的虚拟主机的设定。

在这段设定中,我把*.kiya.cn和*.kiya.us 的Document Root都设定到了 /home/www/www.kiya.us
继续看下去,在这里我就配置了URL Rewrite规则。
RewriteEngine on #打开URL Rewrite功能
RewriteCond %{HTTP_HOST} ^[^.]+.kiya.(cn|us)$ #匹配条件,如果用户输入的URL中主机名是类似 xxxx.kiya.us 或者 xxxx.kiya.cn 就执行下面一句
RewriteRule ^(.+) %{HTTP_HOST}$1 [C] #把用户输入完整的地址(GET方式的参数除外)作为参数传给下一个规则,[C]是Chain串联下一个规则的意思
RewriteRule ^([^.]+).kiya.(cn|us)(.*)$ /home/www/dev.kiya.us/sylvan$3?un=$1&%{QUERY_STRING} [L]
# 最关键的是这一句,使用证则表达式解析用户输入的URL地址,把主机名中的用户名信息作为名为un的参数传给/home/www/dev.kiya.us目录下的脚本,并在后面跟上用户输入的GET方式的传入参数。并指明这是最后一条规则([L]规则)。注意,在这一句中指明的重写后的地址用的是服务器上的绝对路径,这是内部跳转。如果使用http://xxxx这样的URL格式,则被称为外部跳转。使用外部跳转的话,浏览着的浏览器中的URL地址会改变成新的地址,而使用内部跳转则浏览器中的地址不发生改变,看上去更像实际的二级域名虚拟服务器。
设置后重启Apache服务器就大功告成了! (重新让apache重新reload配置即可)

例6. 通过Rewrite防止盗链 (经常看到有的网站对图片盗链有限制,其实设置就是这么简单)
不允许www.im286.com www.chinaz.com 这两个网站盗链 , 其它的网站都可以盗链的规则怎么写.

例7. 关于是否需要使用完全转义,比如在 RewriteCond %{HTTP_REFERER} chinaz.com [NC] 中 把 chinaz.com 改成 chinaz\.com
答案是,两者都是可以的。

例8. 另外几个小例子:
1. 屏蔽IE和Opera浏览器(User-Agent)

2. 自动添加.php扩展名及自动换.html到.php扩展名

3. 限制仅显示图片,而不能显示其他文件的请求。

补充,关于特定文件扩展名的重写。
重写有某些扩展名的文件:
RewriteRule (.*.css$|.*.js$) gzip.php?$1 [L]
如果要排除一些扩展名:
RewriteRule !\.(js|ico|gif|jpg|JPG|png|PNG|css|pdf|swf)$ index.php

参考资料:
摘录资料的博客1:http://slj.me/2009/04/apache-rewrite-regular/
摘录资料的博客2:http://blog.csdn.net/chaiqi/article/details/5620427
apache rewrite官网手册:http://httpd.apache.org/docs/current/mod/mod_rewrite.html
PCRE介绍:http://www.pcre.org/

master

Stay hungry, stay foolish.

2 Comments

发表评论

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

*