Apache Rewrite 理解
因为工作须要,查了一下Apache的文档,对当中反向引用和条件的运行做了理解和实验,以下是对Apache 2.2文档的摘录,并在上面做了实验的样例说明,希望能给一些须要深入理解的一些帮助。
其它部分就不做很多其它的说明,看文档就可以。
Apache的mod_rewrite是提供了强大URL操作的杀手级模块,能够实现差点儿全部你梦想的URL操作,其代价是你必须接受其复杂性,由于mod_rewrite对于刚開始学习的人的主要障碍就是不easy理解和运用,即使是Apache专家有时也会发掘出mod_rewrite的新用途。换句话说:你或者是打退堂鼓永不再用,或者是喜欢它并一生受用。眼下存在这样一种倾向:很多刚開始学习的人仅仅是把URL重写规则当着是会变戏法的魔咒,而并未在使用中真正理解这些规则的含义。
本篇文档试图给出充分的背景知识,以便于刚開始学习的人随后的理解,而不是盲目的复制和粘贴。
mod_rewrite使用的是Perl兼容的正則表達式语法。本文不打算具体解说正則表達式语法,你能够到PCRE man page, Perl regular expression man page, Mastering Regular Expressions, by Jeffrey Friedl获得这些内容。
RewriteRule指令的说明部分有一个简单的正則表達式语法简单介绍,能够去參考一下。
另外须要说明的是能够在表达式的最前面加上一个感叹号('!')表示不匹配,只是这样的使用方法并不符合正則表達式语法。
正則表達式的反向引用能力
这是非常重要的一点:一旦在Pattern或者CondPattern中使用了圆括号,就会建立内部的反向引用,能够使用$N和%N来调用(见下述),而且在Substitution和TestString中都有效。图-2说明了反向引用被转换和展开的位置。

图-2: The back-reference flow through a rule.
内部处理
此模块的内部处理极为复杂,可是为了使一般用户避免犯低级错误,也让管理员能充分利用其功能,在此仍然做一下说明。
API阶段
首先,你必须了解Apache是分若干阶段来处理HTTP请求的。Apache API对每一个阶段都提供了一个hook程序。mod_rewrite使用两个hook程序:其一,从URL到文件名称的转换hook(用在读取HTTP请求之后、授权開始之前); 其二,修正hook(用在授权阶段和读取文件夹级配置(.htaccess)之后、内容处理器激活之前)。
所以,Apache收到一个请求而且确定了响应主机(或虚拟主机)之后,重写引擎即開始处理server级配置中的全部mod_rewrite指令(此时处于从URL到文件名称转换的阶段),此阶段完毕后,终于的数据文件夹便确定了。接下来进入修正程序段并触发文件夹级配置中的mod_rewrite指令。这两个阶段并非泾渭分明的,但都实施了把URL重写成新的URL或者文件名称。尽管API最初不是为此目的而设计的,可是如今它已经成为了API的一种用途。记住下面两点,会有助于更好地理解:
尽管mod_rewrite能够将URL重写为新的URL或文件名称,甚至将文件名称重写为新的文件名称,可是之前的API仅仅提供从URL到文件名称的hook。在Apache 2.0中,添加了两个丢失的hook以使得处理过程更加清晰。只是这样做并没有给用户带来麻烦,用户仅仅需记住这样一个事实:借助从URL到文件名称的hook比最初API设计的目标功能更强大。
令人难以置信的是,mod_rewrite还提供了文件夹级的URL操作(.htaccess文件),而这些文件必须在将URL转换成文件名称之后才会被处理(这是必须的,由于.htaccess存在于文件系统中)。换句话说,依据API阶段,这时再处理不论什么URL操作已经太晚了。为了解决这个"鸡和蛋"的问题,mod_rewrite使用了一个小技巧:在进行一个文件夹级的URL/文件名称操作时,先把文件名称重写回对应的URL(通常这个操作是不可行的,可是參考以下的RewriteBase指令就能明确它是怎么实现的了),然后,对这个新的URL建立一个新的内部的子请求,再又一次開始API阶段的运行。
另外,mod_rewrite尽力使这些复杂的操作对用户透明。但仍须记住:server级的URL操作速度快并且效率高,而文件夹级的操作因为这个"鸡和蛋"的问题速度较慢并且效率也低。但从还有一个側面看,这却是mod_rewrite得以为一般用户提供(局部限制的)URL操作的唯一方法。
牢记这两点!
规则集的处理
当mod_rewrite在这两个API阶段中開始运行时,它会读取配置结构中配置好的 (或者是在服务启动时建立的server级的,或者是在遍历文件夹採集到的文件夹级的)规则集,然后,启动URL重写引擎来处理(带有一个或多个条件的)规则集。不管是server级的还是文件夹级的规则集,都是由同一个URL重写引擎处理,仅仅是终于结果处理不同而已。
规则集中规则的顺序是非常重要的,由于重写引擎是按一种特殊的顺序处理的:逐个遍历每一个规则(RewriteRule指令),假设出现一个匹配条件的规则,则可能回头遍历已有的规则条件(RewriteCond指令)。由于历史的原因,条件规则是前置的,所以控制流程略显冗长,细节见图-1。

图-1:重写规则集中的控制流
可见,URL首先与每一个规则的Pattern匹配,假设匹配失败,mod_rewrite将马上终止此规则的处理,继而处理下一个规则。假设匹配成功,mod_rewrite将寻找相应的规则条件,假设一个条件都没有,则简单地用Substitution构造的新值来替换URL,然后继续处理其它规则;可是假设条件存在,则開始一个内部循环按其列出的顺序逐个处理。对规则条件的处理有所不同:URL并不与模式进行匹配,而是首先通过扩展变量、反向引用、查找映射表等步骤建立一个TestString字符串,然后用它来与CondPattern匹配。假设匹配失败,则整个条件集和相应的规则失败;假设匹配成功,则运行下一个规则直到全部条件运行完成。假设全部条件得以匹配,则以Substitution替换URL,而且继续处理。
比如以下的配置
RewriteEngine on
#设置Rewrite日志
RewriteLogLevel 9
RewriteLog "C:/Apache/logs/rewrite.log"
RewriteCond $1 ^(.*)/.(.*) [NC] (1)
RewriteCond %{HTTP_HOST} !^(.*)/.(.*)/.(.*) (2)
RewriteRule ^/(.*) /$1?ID=%1 (3)
#RewriteCond ............... (4)
#RewriteRule ^/(.*) ............ (5)
如果在浏览器中输入 http://www.domain.com/index.php,server端将会进行例如以下操作
规则集合的运行:逐个遍历每一个规则(RewriteRule指令),发现第(3)行,则用输入 /index.php作为RewriteRule的Pattern进行匹配,假设匹配不成功,则会继续往下处理其它的RewriteRule。假设成功,则会去寻找本条RewriteRule前面的全部RewriteCond,然后从第找到的第一个RewriteCond開始,建立TestString字符串,然后用它来与CondPattern匹配。假设匹配失败,则整个条件集和相应的规则失败;假设匹配成功,则运行下一个规则直到全部条件运行完成。假设全部条件得以匹配,则以Substitution替换URL,而且继续处理。
上面的样例,假设运行到(5),则仅仅会有(4)这个RewriteCond被处理,(3)前面的(1)(2)不会再次被处理,假设開始运行的时候(3)RewriteRule没有匹配,则(1)(2)就不会有被运行的机会。
反向引用:
从前面的样例和上面的图能够看出,
Substitution能够反向引用当前Pattern中的匹配的分组成分(圆括号!)。
引用方法是: $N (0 <= N <= 9)
也能够反向应用RewriteCond条件中最后符合的条件中的分组成分(圆括号!)。记住是最后一个匹配成功的。
引用方法是: %N (1 <= N <= 9)
相同,TestString中能够包括反向引用当前匹配的RewriteRule的Pattern部分的匹配的分组成分(圆括号!)。
引用方法是: $N (0 <= N <= 9)
从处理图看,仅仅能对该RewriteCond前面的被成功处理过的CondPattern分组成分(圆括号!)进行引用,即条件(2)能够对(1)进行反向引用。
Apache Rewrite 理解的更多相关文章
- .htaccess中的apache rewrite规则写法详解
.htaccess中的apache rewrite写法: 1 RewriteEngine On 2 RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ 3 Rewr ...
- Apache Rewrite 规则详解
在开篇之前: 我想说这篇文章其实是我刚刚接触Rewrite的时候学习的文档,应属转载,但是在这里我不想写明原地址,原因是文章中大多数给出的配置命令经实验都是错误的.需要原文的可以在谷歌上搜索一下&qu ...
- Apache rewrite
Apache rewrite mod_rewrite简介和配置 实URL跳转隐藏真实地址 拟目录 域名跳转 防止盗链 Apache配置支持httpd.conf配置.htaccess配置 启用rewri ...
- Apache Rewrite url重定向功能的简单配置
http://www.jb51.net/article/24435.htm 1.Apache Rewrite的主要功能 就是实现URL的跳转和隐藏真实地址,基于Perl语言的正则表达式规范.平时帮助我 ...
- HTTP POST请求的Apache Rewrite规则设置
最近自测后端模块时有个业务需求需要利用WebServer(我用的是Apache)将HTTP POST请求转发至后端C模块,后端处理后返回2进制加密数据.http post请求的url格式为: ...
- Apache rewrite地址重写
Apache-rewrite+13个经典案例Apache 重写规则的常见应用(rewrite)一:目的 如何用Apache重写规则来解决一些常见的URL重写方法的问题,通过常见的 实例给用户一些使用重 ...
- Apache Rewrite(大小写)
1.Rewrite规则简介: Rewirte 主要的功能就是实现URL的跳转,它的正则表达式是基于Perl语言.可基于服务器级的(httpd.conf)和目录级的 (.htaccess)两种方式.如果 ...
- Apache Rewrite规则详解[转]
1.Rewrite规则简介:Rewirte主要的功能就是实现URL的跳转,它的正则表达式是基于Perl语言.可基于服务器级的(httpd.conf)和目录级的(.htaccess)两种方式.如果要想用 ...
- centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课
centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 ...
随机推荐
- SilkTest Q&A 4
Q31.如何在inc文件里面写函数? A31.在你在inc文件(例如demo.inc)里写好函数以后,你需要使用Use path/Use file来指定指定它们. 在SilkTest中->Opt ...
- hibernate学习(二)
hibernate 单向一对多映射 一.数据表设计 数据库名:hibernate5 数据表: ①表名:CUSTOMERS 字段: CUSTOMER_ID CUSTOMER_NAME ②表名:ORDE ...
- Delphi对WM_NCHITTEST消息的处理
前提:WM_NCHITTEST是很重要的,只要鼠标在活动,Windows无时无刻在发这个消息进行探测. ------------------------------------------------ ...
- struts2+jquery +json实现异步加载数据,亲测(原创)
//初始加载页面时 $(document).ready(function(){ //为获取单个值的按钮注册鼠标单击事件 $("#getMessage").click(functio ...
- iOS中的字符串NSString
创建一个字符串对象: NSstring * str1 = @"hello world"; NSString * str = [[NSString alloc]initWithStr ...
- uva 1434 - YAPTCHA(数论)
题目链接:uva 1434 - YAPTCHA 题目大意:给定n和k,求题目中给定的式子S(n). 解题思路:威尔逊定理,x为素数时有,((x−1)!+1)%x==0,所以对于本题.假设3*k+7为素 ...
- 用cocos2d-x 3.2 实现的FlappyBird
近期才開始学cocos2dx,买了几本书还有看大神(主要是 笨木头)的博客.然后就自己尝试用cocos2d-x实现了一下... (新手,勿喷...) 先看执行效果 http://pan.baidu.c ...
- SqlServer操作远程数据库
exec sp_addlinkedserver 'srv2','','mssql2008','服务器IP' exec sp_addlinkedsrvlogin 'srv2','false',null, ...
- If you pay peanuts,you get monkeys
英文原文:Before you send an email to contact a web developer, please read this… 做为一名开发者,我收到很多关于开发新 web 应 ...
- [置顶] hdu 4699 2个栈维护 or 伸展树
hdu 4699 Editor 题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求到k位置的最大的前缀和.. 注意这里的k是在光标之前的, ...