zoukankan      html  css  js  c++  java
  • Apache Rewrite 理解

    因为工作须要,查了一下Apache的文档,对当中反向引用和条件的运行做了理解和实验,以下是对Apache 2.2文档的摘录,并在上面做了实验的样例说明,希望能给一些须要深入理解的一些帮助。

        其它部分就不做很多其它的说明,看文档就可以。

    Apachemod_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来调用(见下述),而且在SubstitutionTestString中都有效。图-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作为RewriteRulePattern进行匹配,假设匹配不成功,则会继续往下处理其它的RewriteRule。假设成功,则会去寻找本条RewriteRule前面的全部RewriteCond,然后从第找到的第一个RewriteCond開始,建立TestString字符串,然后用它来与CondPattern匹配。假设匹配失败,则整个条件集和相应的规则失败;假设匹配成功,则运行下一个规则直到全部条件运行完成。假设全部条件得以匹配,则以Substitution替换URL,而且继续处理。

     

    上面的样例,假设运行到(5),则仅仅会有(4)这个RewriteCond被处理,(3)前面的(1)(2)不会再次被处理,假设開始运行的时候(3RewriteRule没有匹配,则(1)(2)就不会有被运行的机会。

     

    反向引用:

    从前面的样例和上面的图能够看出,

    Substitution能够反向引用当前Pattern中的匹配的分组成分(圆括号!)

    引用方法是: $N  (0 <= N <= 9)

    也能够反向应用RewriteCond条件中最后符合的条件中的分组成分(圆括号!)。记住是最后一个匹配成功的。

    引用方法是: %N  (1 <= N <= 9)

     

    相同,TestString中能够包括反向引用当前匹配的RewriteRulePattern部分的匹配的分组成分(圆括号!)

    引用方法是: $N  (0 <= N <= 9)

    从处理图看,仅仅能对该RewriteCond前面的被成功处理过的CondPattern分组成分(圆括号!)进行引用,即条件(2)能够对(1)进行反向引用。

  • 相关阅读:
    HDU 5912 Fraction (模拟)
    CodeForces 722C Destroying Array (并查集)
    CodeForces 722B Verse Pattern (水题)
    CodeForces 722A Broken Clock (水题)
    CodeForces 723D Lakes in Berland (dfs搜索)
    CodeForces 723C Polycarp at the Radio (题意题+暴力)
    CodeForces 723B Text Document Analysis (水题模拟)
    CodeForces 723A The New Year: Meeting Friends (水题)
    hdu 1258
    hdu 2266 dfs+1258
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4298500.html
Copyright © 2011-2022 走看看