Apache Rewrite功能一应用案例

         今天生产项目上遇到一个棘手的问题,是关于微信公众号开发对接的,这是一个实际的业务场景,相信很多人会遇到,我来讲讲。
        在微信公众号里有一项:网页账号,网页授权获取用户基本信息,点击修改,是授权回调页面域名。这里需要添加一个域名,我们这里是mall.test.com因为之前我们已经对公众号进行了开发了微信商场,已经占用了该域名。但现在我们又开发了新的功能,后续可能更多,而且都是不同的服务器。那么这里我们就没办法在只填一个域名的情况下,实现这些服务了。
微信预约服务调用示意图
weixin


幸好有这个rewrite功能,来解决这个问题。
微信商城的API接口 mall.test.com/api/api.html
预约接口API book.test2.com/book/book.html
这里我们利用rewrite功能来用mall.test.com/book/book.html跳转到book.test2.com/book/book.html 并传递参数。

这里我们在虚拟主机配置或是主配置文件http.conf下添加:

RewriteEngine On  ##开启功能
RewriteCond %{REQUEST_URI} ^/book/    ##匹配请求的连接上下文中以/book/ 开头的
RewriteRule ^book/(.*) http://book.test2.com/book/$1 [R] 
##执行规则将book/后所有的字符串请求都转发book.test2.com/book/ 下
RewriteLog "/usr/local/var/apache/logs/rewrite.log"  ##重写日志路径
RewriteLogLevel 3
##要关闭重写引擎日志,可以简单地设此值为0,关闭所有的重写操作记录。使用较高的Level值会使Apache
##服务器速度急剧下降! 重写日志使用大于2的Level值只用于调试!
 

知识补充:
apache rewrite
重写规则的作用范围,有如下三种:
1) 可以使用在Apache主配置文件httpd.conf中
2) 可以使用在httpd.conf里定义的虚拟主机配置中
3) 可以使用在基本目录的跨越配置文件.htaccess中

首先查看httpd.conf看是否加载了rewrite 模块
centos、RHEL下
去除httpd.conf文件中”#LoadModule rewrite_module modules/mod_rewrite.so”前面的”#”号;
ubuntu 下
sudo a2enmod rewrite

启动模块
RewriteEngine on
将其中的:
Options Indexes FollowSymLinks
AllowOverride all
否则你的.htaccess文件配置不会工作,如果是在目录下使用.htaccess时修改。

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转发),必须用url全称,并且要保证modProxy打开,也就是下面httpd.conf中的如下两个指令:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
如果对应proxy模块没加载,则会出现403禁止页面。

Apache rewrite例子集合,这样更有助于你快速理解rewrite的规则设置及语法。
案例一:
同时达到下面两个需求:
1.用http://www.test.com/xxx.php 来访问http://www.test.com/xxx/
2.用http://abc.test.cn 来访问 http://www.test.com/user.php?username=abc的功能

     RewriteEngine On
     RewriteCond %{HTTP_HOST} ^www.test.com
     RewriteCond %{REQUEST_URI} !^user.php$
     RewriteCond %{REQUEST_URI} .php$
     RewriteRule (.*).php$ http://www.test.com/$1/ [R]
     RewriteCond %{HTTP_HOST} !^www.test.com
     RewriteRule ^(.+) %{HTTP_HOST} [C]
     RewriteRule ^([^.]+).test.cn http://www.test.com/user.php?username=$1

案例二:
新申请域名为www.opensgalaxy.com, 需要将原来的域名www.wujianren.com, 以及论坛所在地址wujianren.com/bbs/定向到新的域名,以便用户可以找到,并且使原来的论坛 URL 继续有效而不出现 404 未找到,比如原来的http://wujianren.com/bbs/abc.html, 让它在新的域名下继续有效,点击后转发到http://bbs.opensgalaxy.com/abc.html,而其他网页,如原先的http://www.wujianren.com/test不会到二级域名bbs.opensgalaxy.com/test上,而是到www.opensgalaxy.com/test

    RewriteEngine On
    RewriteCond %{REQUEST_URI} ^/bbs/
    RewriteRule ^bbs/(.*) http://bbs.opensgalaxy.com/$1 [R,L]
    RewriteCond %{REQUEST_URI} !^/bbs/
    RewriteRule ^(.*) http://www.opensgalaxy.com/$1 [R]

案例三:
/test*.html 被重定向为 /test.php?testid=*
/test*page*.html 被重定向为 /test.php?testid=*&page=*

    RewriteRule ^/test([0-9]+).html$ /test.php?testid=$1 [PT]
    RewriteRule ^/test([0-9]+)page([0-9]+).html$ /test.php?testid=$1&page=$2 [PT]

案例四:
通过Rewrite防止盗链
不允许www.aaa.com www.bbb.com 这两个网站盗链 , 其它的网站都可以盗链的规则怎么写?

    RewriteEngine On
    RewriteCond %{HTTP_REFERER} aaa.com [NC]
    RewriteCond %{HTTP_REFERER} bbb.com [NC]
    RewriteRule .*\.(jpg|jpeg|gif|png|rar|zip|txt|ace|torrent|gz|swf)$ http://www.ccc.com/fdl.png [R,NC,L]

相反,只允许www.ddd.com www.eee.com这两家网站盗链,其他网站都不允许盗链怎么写?

    RewriteEngine On
    RewriteCond %{HTTP_REFERER} !^ddd.com [NC]
    RewriteCond %{HTTP_REFERER} !^eee.com [NC]
    RewriteRule .*\.(jpg|jpeg|gif|png|rar|zip|txt|ace|torrent|gz|swf)$ http://www.ccc.com/fdl.png [R,NC,L]

案例五:
屏蔽IE和Opera浏览器(User-Agent)

    RewriteEngine on
    RewriteCond %{HTTP_USER_AGENT} ^MSIE [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^Opera [NC]
    RewriteRule ^.* – [F,L]    

更多的知识点请参考官方文档http://httpd.apache.org/docs/

发表评论