[重写] Zeus Web Server 上的URL重写指南[基本完成]

[重写] Zeus Web Server 上的URL重写指南[基本完成]

[重写] Zeus Web Server 上的URL重写脚本

  Zeus的重写相对Apache来说,要简单一些,而且流程相对清晰。

  但是有一个限制,他仅仅针对URL的pathname部分,也就是URL之中的目录和文件部分,并且重写为当前domain的另外目录或者文件,而不能重写到其他的domain或者其他的本地文件。这一点相对于Apache来说,功能减弱了很多,不过Zeus也有一些相关的补救措施,例如Subserver等。

  上面这段的简短示例就是,可以把http://www.gaogao8.com/dir_a/file_1.php之中的/dir_a/file_1.php重写为/path_b/file_2.html,但是不能重写为http://www.gaogao9.com/或者/home/www.gaogao9.com/(这里是绝对路径)之下的文件。

  不过,它可以使用重写规则,将URL转向另外一个domain下的网址,但是是发给客户端,又客户端再次请求新的网址。

  Zeus的重写规则一般如下:

[Copy to clipboard] [ - ]
CODE:
match URL into $ with ^/dir/(.*)\.php
if matched then
    set URL=/newpath/$1.html
endif

  其意义非常明确,如果匹配,就做什么操作。这里相对Apache的重写来说,也有一个好处,做什么操作这个地方,可以有多行操作(当然,Apache也可以接连的执行重写规则,但是和这里是不同的)。一行一行的写,看起来至少容易理解。而且它要求必须是一行一个操作。

  Zeus的重写指令之中,是大小写无关的,不过手册建议,关键词使用小写,变量名和标签使用大写。

  Zeus的重写规则之中,有几个关键的信息:关键字、变量、字符串、标签。

  Zeus重写之中,变量用于存储字符串,可以保存单个字符串,也可以保存一个字符串数组。例如当前网址URL,是一个网址字符串,而SCRATCH这样子的变量,就是一个数组,它可以有path和file这样子的元素。

  可用的变量如下:部分变量是只写的,不可读取内容,它用于设置信息进行操作

[Copy to clipboard] [ - ]
CODE:
URL 用户请求的网址的pathname部分,可被重写为新的pathname
REMOTE_HOST 客户端的hostname或者ip(DNS无效时)
REMOTE_ADDR 客户端的ip
REMOTE_USER 在有认证时,是客户的用户名
REQUEST_METHOD 请求方法,例如GET、POST,它是只写的,不可重写改变

ENV 字符串数组,包含操作系统的变量,可以设置值或者添加新的值,它是只写的。
IN 字符串数组,包含HTTP请求头信息,可被重写改变头信息
OUT 字符串数组,在请求完成时,它保存发送给用户的HTTP头信息;初始是空的。它是只写的。
SCRATCH 字符串数组,可以用来保存临时数据,请求结束时,数据清空。
NOTES 字符串数组,可以用来存储备注信息,可以用来保存到日志,也可以通过API被程序读取操作
BODY 用于替换发送给用户的页面内容,发送之后Zeus就会断开连接,它是只写。
RESPONSE 如果BODY设置了,它可以设置为发给客户端的HTTP响应代码。

  Zeus的关键字也就是指令,包含以下指令:

QUOTE:

  • match指令 匹配操作,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    [insensitive] match 变量 into 数组 with 正则表达式

    insensitive 表示注意大小写,可以不用,则不区分大小写
    变量 可以是前面列出的任何可被读取的变量
    数组 表示匹配之后的结果保存的数组,只能是$或者%,根据配分组为$1...%1...
    正则表达式 用于匹配的正则表达式

    如果匹配成功,则matched标志被置为true,否则为false。
    正则表达式之中的匹配分组结果,将被放入$或者%数组。

  • if指令 判断操作,仅针对匹配或者检查是否成功,语法如下,分为单行操作或者多行操作

    [Copy to clipboard] [ - ]
    CODE:
    if [not] (matched|exists) 操作



    [Copy to clipboard] [ - ]
    CODE:
    if [not] (matched|exists) [then]
        指令
       ...
       指令
    [else
        指令
       ...
        指令]
    endif

      matched就表示前面的匹配是否成功,exists表示look操作的检查是否成功。其他的意义比较简单明确,不作解释了。

  • set指令 用于给变量赋值,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    set 变量 操作符 字符串

      变量 前面描叙的可写的变量
      操作符 可使用=或者.,=表示直接赋值,.表示连接赋值
      字符串 被赋的值

  • goto指令 用与标签的跳转,可以改变重写规则的流程,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    goto 标签

      在使用goto指令的时候需要小心,不要搞一个无限循环啊。

  • map指令 获取实际文件路径或者MIME类型操作,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    map (path|mime) into 变量 from URL相对路径


  path 表示获取URL相对路径的实际文件路径。例如网站根目录为/var/www/www.test.com,则URL相对路径为/时,变量的值将是/var/www/www.test.com/。
  mime 表示获取URL相对路径所对应的文件的MIME类型,例如是/test/index.html,它将获取.html的MIME类型,也就是text/html
  变量 存储从path或者mime获取的字符串值,如果获取失败则为空;存储到SCRATCH之中,例如SCRATCH:mypath
  URL相对路径 也就是网址中的pathname部分。也可以使用一个变量
 
  这个指令,简单来说,就是获取所访问的文件的本地文件系统路径或者MIME类型。

  • look指令 检查所访问的文件或者路径是否存在,类似Apache的-d和-f这样子的参数的作用,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    look for (dir|file) at URL相对网址

      dir 检查是否为目录
      file 检查是否为文件
      URL相对网址 和前面的相同,从网站根目录算起的。也可以使用一个变量
      如果检查成功,则exists标志被置为true,否则为false,然后可用在if指令中控制流程。
      有一点需要说明的就是:look了之后,前面的matched标志将会无效,除非再次match;反之,match也会使得exists标志无效

  • execute指令 外部重写脚本,类似apache的RewriteMap,但是功能不同,这里只能是Zeus的重写脚本指令集,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    execute 脚本

      脚本 需要执行的重写脚本的完整本地文件路径。
      这个指令,可以用于书写大段的重写脚本,他可以继续使用之前匹配的$1~$9或者%1~%9,也可以使用SCRATCH之中的数据。为了防止执行不存在的脚本,你可以首先使用look检查脚本文件是否存在。

  • restart指令 重新处理连接,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    restart

      这个指令到底有什么用呢?它可以在你设置一些环境变量之中,将本次请求重新处理,并且应用已经设置的环境变量。
      例如:以下的指令,可以把当前的请求的HTTP头之中的Host修改为www.test2.com,然后把当前连接直接转移到www.test2.com来处理,而不需要客户端的重定向操作

    [Copy to clipboard] [ - ]
    CODE:
    set IN:Host = www.test2.com
    restart

      
  • substr指令 从字符串截取部分字符操作,语法如下:

    [Copy to clipboard] [ - ]
    CODE:
    substr 目的变量 is 原始字符串变量 from 开始位置 for 截取长度

      目的变量 保存截取到的字符串
      原始字符串 原始操作字符串变量
      开始位置,截取长度 从什么位置截取多少个字符

  从前面的介绍,我们可以得知,重写基本上是对字符串的操作,或者是保存了字符串的变量。在Zeus的重写之中,字符串里面可以嵌入变量,使用%{}来嵌入一个变量,例如:

[Copy to clipboard] [ - ]
CODE:
/var/www/%{IN.Host}/public_html

  你也可以将匹配结果$1~$9或者%1~%8嵌入。

  上面有一个goto指令,用于跳转到标签;标签可以使用大小写字母、数字、下划线或者减号定义,一般形式如下:

[Copy to clipboard] [ - ]
CODE:
LABEL:

  :是必须的,表示这是一个标签,而且标签所在行不能有其他的操作指令。
  标签可以放在脚本的任何地方,你爱怎么跳转就怎么跳转,只要不转来转去转晕头就成。
  另外,还有两个预定义的标签,BEGIN:和END:,这两个标签是自动定义的,一个在所有规则最前面,一个在所有规则最后面,使用goto END可以结束所有规则。你不能覆盖这两个标签的定义。

  通过标签的跳转,可以使得部分重写规则不被执行,如果你想保留这些规则在脚本之中,但是有暂时不打算执行,你可以直接在规则前后应用goto和标签来跳过,也可以把这些规则注释掉,类似Apache,#用来将一行注解掉,当然,在注解行,你也可以写一些备注的信息。

  goto可以在规则之间调来调去,如果你学过早期的BASIC的话,可以使用goto来实现一些小的函数功能,这里我们就不说了。
  另外,规则也是可以相互嵌套的,例如if之内,好可以嵌套一个if,形成多重条件判断。不过记住,每次match或者look以后,原有的exists或者matched都会被置为无效的,这点需要注意。
  

规则演示:

[Copy to clipboard] [ - ]
CODE:
#将当前网站的根目录读取到SCRATCH:documentroot之中
map path into SCRATCH:documentroot from /
#匹配当前网址中是否有字符a
match URL into $ with a
#如果匹配到了,则
if matched
    #匹配网址中是否有字符b
    match URL into $ with b
    #如果匹配到了,则
    if matched
        #检查当前请求的网址,是不是一个实际存在的文件
        look for file %{SCRATCH:documentroot}/%{URL}
        #如果文件存在,则
        if exists then
            #将网址重写到/yes_a_yes_b.php,并且传递一个变量,file为1
            set URL = /yes_a_yes_b.php?file=1
        else
            #将网址重写到/yes_a_yes_b.php,并且传递一个变量,file为0
            set URL = /yes_a_yes_b.php?file=0
        endif
    else
        set URL = /yes_a_not_b.php
    endif
else
    match URL into $ with b
    if matched
        #将网址对应文件的mime类型读取出来
        map mime into SCRATCH:mimetype from URL
        #将网址重写,并把mime类型作为参数传递
        set URL = /not_a_yes_b.php?mimetype=%{SCRATCH:mimetype}
    else
        set URL = /not_a_not_b.php
    endif
endif

  以上的介绍之中,有几点指出:
1. SCRATCH 这个变量用于存储临时数据,随便怎么放都可以,需要使用时,如果是放到字符串之中,则使用%{SCRATCH:属性索引}
2. IN 这个变量存储HTTP头信息,具体有些什么,你可以在程序里面输出环境信息看到,例如PHP的phpinfo()就可以看到,在HTTP Headers Information部分
3. 不要把它想的过于复杂,尽量把你所期望的东西,写到纸上,并且是一步一步的非常清晰的流程,再转换成规则,就会很简单。当然,也不能想的太过简单了。
4. 多多实践,多多测试,日志里面会纪录错误信息的
  Zeus的重写之中所用到的正则,如果你想深入的了解和学习,那么你可以看看这本书,很好:http://books.google.com/books?q=Mastering+Regular+Expressions&ots=-gA_jy4c-2&sa=X&oi=print&ct=title

  不过事先说明一点,正则是个非常好的东西,以至于有的人会用得快乐至癫,而有的人会被它折磨致死。要死要活,你自己考虑吧,没有人可以为你的生死给出建议。

  正则就用在match指令之中,下面我们简单说说其中所用到的正则,你可以马上进行测试。

  首先说一下子,在正则之中,我们会使用一个特殊符号表示特殊的意义的。例如C语言的*,&,PHP的$等等。因为这些字符有其特殊的作用和含意,如果我们要使用它本身二步包含特殊含义,就需要使用\这个符号来限制它,特别的,\\表示限制自己,就表示一个\的符号了(是一个\,而不是两个)。

  正则之中,首要的,也是最简单的部分,就是匹配什么东西,例如:abc、123,简单的字符串或者数组,或者任何东西。这样子的匹配是连续的,也就是abc需要同时存在而且是连续的。

  如果我们想要匹配a或者b,则可以使用(a|b),表示匹配a或者b,同样可以使用(abc|123),意义你应该知道是什么了。

  然后正则之中,如果匹配单个的a或者b或者c,可以使用[abc],[]之中的内容,表示每次匹配任意一个;特别的,如果是[^开头,则表示不匹配其中的内容。

  我们来一个复杂一点点的联系,我要匹配3后面跟着a或者b或者c,然后跟着的不是c或者d或者e,然后跟着123或者456,则:

[Copy to clipboard] [ - ]
CODE:
3[abc][^cde](123|456)

  有时候,我们可能需要匹配单个字符是在一个确定的范围,例如a-z、1-9,则[a-z]、[1-9]可以使用,也就是说,如果[]之中使用了-,则一般表示匹配的单个字符在两者之前,当然,如果-在最前面或者最后面,近近表示它自己,一个-而已,如果在中间,那么我们可以使用前面所说的\-来表示一个-。

  上面说的都是确定的字符串,如果我们就要匹配一个字符串,我也不知道这个字符串到底会是个什么玩意,那怎么办?使用.就可以,例如abc.456,则表示abc后面跟一个什么玩意,然后在跟着456。如果近近表示.本身,则使用\.

  .表示一个什么玩意,如果要表示多个什么玩意呢?
  .*表示0个或者任意个什么玩意
  .+表示一个或者多个什么玩意
  .?表示0个或者一个什么玩意
  这其中的.也可以是其他的字符,或者()之中的字符串。
  例如至少存在一个.com,则使用(\.com)+

  前面说的都是在一个字符串里面匹配到什么东西,如果我们要准确的匹配整个字符串,怎么办?
  ^这个表示从字符串的开头开始匹配
  $这个表示一直匹配到字符串的结尾
  例如,我们要匹配www.a.com或者www.b.com或者...或者www.z.com,则使用
  ^www\.[a-z]\.com$
  ^和$不必同时使用,例如匹配www开头的,则^www即可,而.cn结尾的,则\.cn$即可

  在前面的介绍之中,我们说了匹配的结果可以被使用,用$1~$9或者%1~%9来调用,那么如何产生这个$或者%的变量呢?
  答案很简单,使用(),如果一串字符串被()圈起来,而且被匹配到了,那么他们之中实际匹配到的内容会被放入$或者%之中。
  1~9,顾名思义,是整个规则之中的第一个()....第九个()的匹配内容。

  例如,我需要取得客户端IP的每个部分,则
  match REMOTE_ADDR into $ ^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$
  匹配完成,如果成功,则$1~$4分别放着四位IP地址的每个段。
附加说明:我还没有一个Zeus Web Server的运行实例,也没有使用过,不过正打算测试;所以上面的内容仅仅根据个人对重写的理解,以及查看Zeus的手册所翻译、理解得来的,如有不当之处,敬请指出,谢谢!

更多的内容,在我逐步了解之后,会有更多释出。
看到这里就知道有希望了。顶起
还是多举些例子吧,看的规则真多,rewrite还没学通呢 哈哈

斑竹辛苦了
Zeus中文技术交流群:1157169
无意间在一个论坛上看到 zeus web server 4.3R4最新版破解(http://www.chinazeus.com/read.php?tid=4),那位高人用过这个?怎么样,能用吗?给点意见吧!