重写规则的条件(RewriteCond)

重写规则的条件(RewriteCond) 
重写规则的条件 RewriteCond 
Syntax: RewriteCond TestString CondPattern [flags] 
  RewriteCond指令定义一条规则条件。在一条RewriteRule指令前面可能会有一条或多条RewriteCond指令,只有当自身的模板(pattern)匹配成功且这些条件也满足时规则才被应用于当前URL处理。 
  TestString是一个字符串,除了包含普通的字符外,还可以包括下列的可扩展结构: 
$N,RewriteRule后向引用,其中(0 <= N <= 9) 
  $N引用紧跟在RewriteCond后面的RewriteRule中模板中的括号中的模板在当前URL中匹配的数据。 
%N,RewriteCond后向引用,其中(0 <= N <= 9) 
  %N引用最后一个RewriteCond的模板中的括号中的模板在当前URL中匹配的数据。 
${mapname:key|default},RewriteMap扩展. 
具体参见RewriteMap 
%{ NAME_OF_VARIABLE } ,服务器变量。 
变量的名字如下表(分类显示) 
HTTP headers: connection & request: server internals: system stuff: HTTP_USER_AGENTREMOTE_ADDRDOCUMENT_ROOTTIME_YEARHTTP_REFERERREMOTE_HOSTSERVER_ADMINTIME_MONHTTP_COOKIEREMOTE_USERSERVER_NAMETIME_DAYHTTP_FORWARDEDREMOTE_IDENTSERVER_ADDRTIME_HOURHTTP_HOSTREQUEST_METHODSERVER_PORTTIME_MINHTTP_PROXY_CONNECTIONSCRIPT_FILENAMESERVER_PROTOCOLTIME_SECHTTP_ACCEPTPATH_INFOSERVER_SOFTWARETIME_WDAYQUERY_STRINGTIMEAUTH_TYPE
specials: 说明API_VERSIONApache与模块间的接口的版本号THE_REQUEST客户端发送到来的HTTP请求行的整行信息,不含其它的头字段信息,如("GET /index.html HTTP/1.1")REQUEST_URIHTTP请求行中请求的资源REQUEST_FILENAME请求中对应的服务器本地文件系统中全路径文件名IS_SUBREQ根据是否为SubRequest,分别值为”true”或”false” 
特别说明: 
SCRIPT_FILENAME和REQUEST_FILENAME变量含有相同的值,也就是Apache服务器内部数据结构request_rec的filename字段的值。第一个变量是一个CGI变量,而第二个则与REQUEST_URI(含有request_rec数据结构中uri字段的值)保持一致。 
%{ENV:variable}中的variable可以是任何环境变量的名字。对其值的查找,先通过Apache内部的数据结构,(如找不到)再在Apache服务器进程中通过getenv()查找。 
%{HTTP:header}中的header可以是任何HTTP MIME-header的名字,其值通过查找HTTP请求信息而得。 
%{LA-U:variable} 用来引用后续API阶段中定义的、当前还不知道的值,具体实现是通过执行一个基于URL的内部的sub-request来决定的variable的最终的值。例如,假如你想在服务器范围内利用REMOTE_USER的值来完成重写,但这个值是在验证阶段设置的,而验证阶段是在URL转换阶段的后面。从另一方面讲,由于mod_rewrite在修补(fixup)API阶段进行目录范围的重写,而修补阶段在验证阶段的后面,所以此时只要用%{REMOTE_USER}就可以取得该值了。 
%{LA-F:variable},执行一个基于文件名字(filename)的内部sub-request来决定variable的最终的值。大多数时间内,这和LA-U相同。 
  CondPattern是一个条件模板,也就是说,是一个扩展正则式(extended regular expression),用与跟TestString进行匹配。作为一个标准的扩展正则式,CondPattern有以下补充: 
可以在模板串前增加一个!前缀,以用表示不匹配模板。但并不是所有的test都可以加!前缀。 
CondPattern中可以使用以下特殊变量: 
' 将condPattern当作一个普通字符串,将它和TestString进行比较,当TestString 的字符小于CondPattern为真. 
'>CondPattern' (大于) 
将condPattern当作一个普通字符串,将它和TestString进行比较,当TestString 的字符大于CondPattern为真. 
'=CondPattern' (等于) 
将condPattern当作一个普通字符串,将它和TestString进行比较,当TestString 与CondPattern完全相同时为真.如果CondPattern只是 "" (两个引号紧挨在一起) 此时需TestString 为空字符串方为真. 
'-d' (是否为目录) 
将testString当作一个目录名,检查它是否存在以及是否是一个目录. 
'-f' (是否是regular file) 
将testString当作一个文件名,检查它是否存在以及是否是一个regular文件. 
'-s' (是否为长度不为0的regular文件) 
将testString当作一个文件名,检查它是否存在以及是否是一个长度大于0的regular文件 
'-l' (是否为symbolic link) 
将testString当作一个文件名,检查它是否存在以及是否是一个 symbolic link. 
'-F' (通过subrequest来检查某文件是否可访问) 
检查TestString是否是一个合法的文件,而且通过服务器范围内的当前设置的访问控制进行访问。这个检查是通过一个内部subrequest完成的, 因此需要小心使用这个功能以降低服务器的性能。 
'-U' (通过subrequest来检查某个URL是否存在) 
检查TestString是否是一个合法的URL,而且通过服务器范围内的当前设置的访问控制进行访问。这个检查是通过一个内部subrequest完成的, 因此需要小心使用这个功能以降低服务器的性能。 
  [flags]是第三个参数,多个标志之间用逗号分隔。 
'nocase|NC' (不区分大小写) 
  在扩展后的TestString和CondPattern中,比较时不区分文本的大小写。注意,这个标志对文件系统和subrequest检查没有影响. 
'ornext|OR' (建立与下一个条件的或的关系) 
  默认的情况下,二个条件之间是AND的关系,用这个标志将关系改为OR。例如: 
RewriteCond %{REMOTE_HOST} ^host1.* [OR] 
RewriteCond %{REMOTE_HOST} ^host2.* [OR] 
RewriteCond %{REMOTE_HOST} ^host3.* 
RewriteRule ... 
如果没有[OR]标志,需要写三个条件/规则. 
例子:根据客户端浏览器的不同,返回不同的首页面。 
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.* 
RewriteRule ^/$ /homepage.max.html [L] 
RewriteCond %{HTTP_USER_AGENT} ^Lynx.* 
RewriteRule ^/$ /homepage.min.html [L] 
RewriteRule ^/$ /homepage.std.html [L] 
重写影射、目录(RewriteMap RewriteBase) 
重写影射 RewriteMap 
Syntax: RewriteMap MapName MapType:MapSource 
  RewriteMap指令定义一个重写影射(Rewriting Map),在规则的substitution串中,通过影射函数(mapping-functions)来查找关键字(key),并用关键字对应的值来进行来行插入或替换操作。这个查找的对象,可以是各种各样的。 
  MapName是影射的名字,将用来通过下列的某种结构来为substitution定义影射函数: 
${ MapName : LookupKey } 
${ MapName : LookupKey | DefaultValue } 
当这些结构之一出现substitution串中时,重写引擎会到mapname影射中查找lookupkey关键字,如果找到了就用返回的值(substvalue)来替换该结构,如果找不到就用defaultvalue来替换该结构,如果没有defaultvalue,就用空串来替换。 
  MapType 和mapSource组合有以下几种: 
标准的普通文本(Standard Plain Text) 
MapType: txt, MapSource: Unix文件系统中合法的带有路径的regular file名 
此种情况下,MapSource文件是一个普通的ASCII文本文件,可以含有空行、注释行(以#打头),及以下结构的键值对行(每个键值对一行)。 
MatchingKey SubstValue 
例如:Mapsource文件叫/path/to/file/map.txt,其内容为 
## 
## map.txt -- rewriting map 
## 
Ralf.S.Engelschall rse # Bastard Operator From Hell 
Mr.Joe.Average joe # Mr. Average 
在配置文件中则可以这样定义重写映射: 
RewriteMap real-to-user txt:/path/to/file/map.txt 
随机的普通文本(Randomized Plain Text) 
MapType: rnd, MapSource: Unix文件系统中合法的带有路径的regular file名 
  这种情况与标准普通文本情况很相似,差别只是在SubstValue的格式上:此时的SubstValue由一些用”|”分隔的值组成的串,这个“|”是“或者”的意思。当根据键值找到对应的SubstValue后,mod_rewrite借助“|”将此串分解为一些候选项,然后随机选择一项作为最终的SubstValue的值返回。这听起来有点疯狂或毫无用处,其实这是设计用来在反向代理(reverse proxy)的情况下做负载均衡,用来查找服务器的名字。 
例如:MapSource文件的名字为/path/to/file/map.txt,内容如下: 
## 
## map.txt -- rewriting map 
## 
static www1|www2|www3|www4 
dynamic www5|www6 
在配置文件中定义的重写影射为: 
RewriteMap servers rnd:/path/to/file/map.txt 
Hash File 
MapType: dbm, MapSource: Unix文件系统中合法的带有路径的regular file名 
  这儿的Mapsource文件是一个二进制的NDBM格式的文件,含有与普通文本格式文件时相同的内容,为了实现快速查找进行了优化处理后以一种特殊的格式来表达。 可以用任何NDBM工具或者用下面的Perl脚本txt2dbm.pl来创建这种格式的文件: 
#!/path/to/bin/perl 
## 
## txt2dbm -- convert txt map to dbm format 
## 
use NDBM_File; 
use Fcntl; 
($txtmap, $dbmmap) = @ARGV; 
open(TXT, "<$txtmap") or die "Couldn't open $txtmap!\n"; 
tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644) or die "Couldn't create $dbmmap!\n"; 
while () { 
next if (/^\s*#/ or /^\s*$/); 
$DB{$1} = $2 if (/^\s*(\S+)\s+(\S+)/); 

untie %DB; 
close(TXT); 
此脚本的使用方法如下: 
$ perl txt2dbm.pl map.txt map.db 
Apache内部函数(Internal Function) 
MapType: int, MapSource: Apache内部函数 
  这时,MapSource是一个Apache内置函数,目前还不能创建自己的内部函数,只能使用Apache已经定义好的: 
toupper 
将键值转换为大写 
tolower 
将键值转换为小写 
escape 
将键值中的特殊字符转换为以16进制表示。 
unescape 
将键值中16进制表示的特殊字符转换为原来的样子。 
外部重写程序(External Rewriting Program) 
MapType: prg, MapSource: Unix文件系统中合法的带有路径的regular file名 
  这儿的MapSource是一个程序而不是一个影射文件。你可以使用任何语言创建这个程序,但这个程序必须是可执行的(也就是说,要么是二进制码,要么是首行带有”#!/path/to/interpreter”格式的解释器的可执行脚本)。 
  这个程序在Apache启动时被运行,然后它就用它的标准输入与标准输出的文件句柄与重写引擎通信(暗指程序能无限时等待标准输入,见下列)。对每个影射函数的查找要求,它把其标准输入中得到的字符串(newline-terminated string?)作为键值,然后通过标准输出返回查找到的值,如果找不到相应的值,则返回以四字符的字符串”NULL“。下面一个简单的例子,实现将键值作为查找结果返回: 
#!/usr/bin/perl 
$| = 1; 
while () { 
# ...put here any transformations or lookups... 
print $_; 

注意: 
``Keep it simple, stupid'' (KISS),因为当规则执行时,一量这个外部程序挂起,整个Apache服务器就挂起了 
避免下述常见错误:缓存了标准输出的I/O。这会导致死循环。这也是为什么上例中有``$|=1''这么一行的原因 
用RewriteLock指令定义一个lockfile,以同步与外部程序的通信。默认情况下并没有这样的同步 
  RewriteMap可以出现不只一次。每个影射函数用RewriteMap来声明它的影射文件. While you cannot declare a map in per-directory context it is of course possible to use this map in per-directory context.(?)对普通文本和DBM格式的文件,其键值被缓存在Apache内核中,直到影射文件的mtime 变化了或Apache重启动了。此时,可以将规则中的影射函数用于每个请求。 
RewriteBase 
Syntax: RewriteBase URL-path 
  RewriteBase明确地指出目录范围内的重写结果的baseURL.RewriteRule指令可以用在目录范围内的配置文件里(.htaccess)。在目录范围的重写实施时,由本地路径信息构成的前缀已经被去掉,重写规则只对剩余的部分进行处理。处理结束后,被去掉的路径信息要自动加上,因为当对一个URL进行替换后,重新引擎需要将它重新插入到服务器的处理流程中去。如果服务器端的URL与文件的物理路径有直接有关系,则每当在.htacess文中定义重写规则时都需要用RewriteBase指URL-path。 
杂项Environment Variables 
  mod_rewrite还维护着两个非标准的CGI/SSI环境变量,名为SCRIPT_URL和 SCRIPT_URI,存放着当前资源的逻辑web视图(logical Web-view)。标准的CGI/SSI变量SCRIPT_NAME 和 SCRIPT_FILENAME中存放着当前资源的物理系统视图(physical System-view)。请看例子: 
SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html 
SCRIPT_FILENAME=/u/rse/.www/index.html 
SCRIPT_URL=/u/rse/ 
SCRIPT_URI=http://en1.engelschall.com/u/rse/

你可能感兴趣的:(apache,数据结构,应用服务器,正则表达式,perl)