rewrite!!

rewrite规则:
+----------------------------------------------------------------------------------------+
此模块提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求.它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操作机制.
此URL操作可以依赖于各种测试,比如服务器变量,环境变量,HTTP头,时间标记,甚至各种格式的用于匹配URL组成部分的查找数据库.

此模块可以操作URL的所有部分(包括路径信息部分),在服务器的httpd.conf和目录级的.htaccess配置都有效,还可以最终生成请求字符串.此重写操作的结果可以是内部子处理,也可以是外部请求的转向,甚至是内部代理处理

但是,所有功能和灵活性带来一个问题,那就是复杂性,因此不要指望一天内就能看懂整个模块.
+----------------------------------------------------------------------------------------+
在apache1.3中,TestString和Substitution中的特殊字符可以用前导斜杠(\)来实现转义(即忽略其特殊含义而视为普通字符).比如,Substitution可以用"\$"来包含一个美元符号,以避免apache将其看作为一个反向引用
+----------------------------------------------------------------------------------------+
环境变量:
此模块会跟踪两个额外的(非标准)CSI/SSI环境变量,SCRIPT_URL和SCRIPT_URI.他们包含了当前资源的逻辑网络视图,而标准的CGI/SSI变量SCRIPT_NAME和SCRIPT_FILENAME包含的是物理系统视图.

注意,这些变量保持的是其最初被请求时的URI/URL,即在任何重写操作之前的URI/URL.其重要性在于他们是重写URL到物理路径名称的原始数据.
示例:
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/
+----------------------------------------------------------------------------------------+
实用方案:
我们提供了URL重写指南和高级URL重写指南文档,列举了许多基于URL的问题的使用方案,其中你可以找到真实有用的规则集

RewriteBase指令显示地设置了目录级重写的基准URL.在下文中,你可以看见RewriteRule可以用于目录级的配置文件中(.htaccess)并在局部范围内起作用,即规则实际处理的只是隔离本地路径前缀的一部分,处理结束以后,这个路径会被自动地附着回去.默认是"RewriteBase physical-directory-path",

在对一个新的URL进行替换时,此模块必须把这个URL重新注入到服务器处理中.为此,他必须知道其对应的URL前缀或者是URI基准.通常,此前缀就是对应的文件路径.但是,大多数网站URI不是直接对应于其物理文件路径的,因而不能做这样的假定.所以在这种情况下,就必须用RewriteBase指令来指定正确的URI前缀.

>>如果你的网站服务器URL不是与物理文件路径直接对应的,而又需要使用RewriteBase指令,则必须在每个对应的.htaccess文件中指定RewriteRule

例如,目录级配置路径内容如下:
#
# /abc/def/.htaccess -- per-dir config file for directory /abc/def
# Remember: /abc/def is the physical path of /xyz, i.e., the server
# has a 'Alias /xyz /abc/def'directive 例如
#
RewriteEngine On
# let the server know that we were reached via /xyz and not
# via the physical path prefix /abc/def
RewriteBase /xyz

#now the rewriting rules
RewriteRule ^oldstuff\.html$ newstuff.html

上述例子中,对/xyz/oldstuff.html的请求被正确地重写为物理的文件/abc/def/newstuff.html

For Apache Hackers
以下列出内出处理的详细步骤:
Request:
/xyz/oldstuff.html

Internal Processing:
/xyz/oldstuff.html ->/abc/def/oldstuff.html (pre-server Alias)
/abc/def/oldstuff.html -> /abc/def/newstuff.html (per-dir RewriteRule)
/abc/def/newstuff.html -> /xyz/newstuff.html (per-dir RewriteBase)
/xyz/newstuff.html -> /abc/def/newstuff.html (per-server Alias)

Result:
/abc/def/newstuff.html

虽然这个过程开起来很繁复,但是由于目录级重写到来的时机已经太晚,他不得不把这个(重写)请求重新注入到Apache核心中,所以Apache内部确实是这样处理的.但是,它的开销并不像看起来那么大,因为重新注入到Apache服务器内部运行,而且这样的过程在Apache内部也为其他许多操作所使用.所以,你可以充分信任其设计和实现都是正确的
+----------------------------------------------------------------------------------------+
+----------------------------------------------------------------------------------------+
RewriteCond指令

说明:定义重写发生的条件
语法:RewriteCond TestString CondPattern
作用域:server config,virtual host,directory,.htaccess
覆盖项:FileInfo
状态:扩展(E)
模块:mod_rewrite

RewriteCond指令定义了一个规则的条件,即在一个RewriteRule指令之前有一个或多个RewriteCond指令.条件之后的重写规则仅仅在当前的URL与pattern匹配并复合这些条件的时候才会起作用.

TextString是一个纯文本的字符串,但是还可以包含下列可扩展的部分.

RewriteRule反向引用,引用的方法是:
$N

(0<=N <=9)引用当前(带有若干RewriteRule指令的)RewriteCond中的与pattern匹配的分组部分(圆括号)

RewriteMap扩展,引用的方法是:
$(mapname:key|default)
细节看RewriteMap指令

服务器变量,引用方法是:
%{NAME OF VARIABLE}

NAME_OF_VARIBLE可以是下表中列出的字符串之一;
-------------------------------------------------------
HTTP headers: | connection & request
-------------------------------------------------------
HTTP_USER_AGENT REMOTE_ADDR
HTTP_REFERER REMOTE_HOST
HTTP_COOKIE REMOTE_PORT
HTTP_FORWARDED REMOTE_USER
HTTP_HOST REMOTE_IDENT
HTTP_PROXY_CONNECTION REQUEST_METHOD
HTTP_ACCEPT SCRIPT_FILENAME
PATHINFO
QUERY_STRING
AUTH_TYPE
-------------------------------------------------------
server internals data and time: specials
-------------------------------------------------------------------------------
DOCUMENT_ROOT TIME_YEAR API_VERSION
SERVER_ADMIN TIME_MONTH THE_REQUEST
SERVER_NAME TIME_DAY REQUEST_URI
SERVER_ADDR TIME_HOUR REQUEST_FILENAME
SERVER_PORT TIME_MIN IS_SUBREQ
SERVER_PROTOCOL TIME_SEC HTTPS
SERVER_PROTOCOL TIME_WDAY
TIME
-------------------------------------------------------------------------------
这些变量都对应于类似命名的HTTP MIME头,Apache服务器的C变量,Unix中的struct tm字段,其中的大多数在其他的手册或者CGI规范中都有说明,其中mod_rewrite所持有的变量如下:

IS_SUBREQ
如果正在处理的请求是一个子请求,他将包含字符串串"true",否则就是"false"/模块为了解析URI中的附加文件,可能会产生子请求.

API_VERSION
这是正在使用的Apache模块API(服务器和模块之间内部接口)的版本,其定义位于include/ap_mmn.h中,此模块API版本对应于正在使用的Apache的版本.通常,对其感兴趣的是模块的开发者

THE_REQUEST
这是由浏览器发送的完整的HTTP请求(比如:"GET /index.html HTTP/1.1").它不包含任何浏览器发送的其他信息.

REQUEST_URI
这是在HTTP请求行中所请求的资源(比如上述例子中的"index.html")
REQUEST_FILENAME
这是与请求相匹配的完整的本地文件系统的文件路径名
HTTPS
如果连接使用了SSL/TLS,他将包含字符串"on",否则就是"off"(无论mod_ssl是否加载,该变量都可以安全的使用)

其他注意事项:
1.SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的----即Apache服务器内部的request_rec结构中的filename字段.第一个就是大家都知道的CGI变量名,而第二个则是REQUEST_URI(request_rec结构中的url字段)的一个副本
2.特殊形式:%{ENV:variable}%,其中的variable可以是任意环境变量.它是通过查找Apache内部结构或者(如果没有找到的话)由Apache服务器进程getenv()得到的
3.特殊形式:%{SSL:variable},其中的variable可以是一个SSL环境变量的名字,无论mod_ssl模块是否已经加载都可以使用(未加载时为空字符串)!比如:
%{SSL:SSL_CIPHER_USEKEYSIZE}将会被替换为128
4.特殊形式:
%{HTTP:header},其中的header可以是任意HTTP MIME头的名称.他总是可以通过查找HTTP请求而得到.比如%{HTTP:Proxy-Connection}将被替换为Proxy-Connection:HTTP头的值
5.预设形式:
%{LA-U:variable},variable的最总值在执行一个内部(基于URL的)子请求后确定.当需要使用一个目前未知但是会在以后的过程中设置的变量的时候,可以使用这个方法.例如,需要在服务器配置httpd.conf文件中根据REMOTE_USER变量进行重写,就必须使用%{LA-U:REMOTE_USER}.因为此变量是由URL重写{mod_rewrite}步骤之后的认证步骤设置的.但是另一方面,因为mod_rewrite是通过api修正步骤来实现目录级(.htaccess文件)配置的,而认证步骤先于API修正步骤,所以可以用%{REMOTE_USER}
6.预设形式:
%{LA-F:variable},variable的最终值在执行一个内部(基于文件名)子请求后确定.大多数情况下和上述的LA-U是相同的.

CondPattern是条件模式,即一个应用于当前TestString实例的正则表达式.TestString将被首先计算,然后再与CondPattern匹配.
------------------------------------------------------------------------------------------
ConPattern是一个perl兼容的正则表达式,但是还有若干增补:
1.可以在CondPattern串的开头使用"!"来指定不匹配
2.condPatterns有若干特殊的变种.除了正则表达式的标准用法,还有下列用法:
.'<CondPattern'(词典顺序的小于)
将CondPattern视为纯字符串,与TestString按词典顺序进行比较!如果TestString小于CondPattern则为真
.'>CondPattern'词典顺序为>
将CondPattern视为纯字符串,与TestString按词典顺序进行比较.如果TestString大于CondPattern则为真.
.'=CondPattern'词典顺序的等于
将CondPattern视为纯字符串,与TestString按词典顺序进行比较.如果TestString等于CondPattern(两个字符串地完全相等)则为真.如果CondPattern是""两个双引号,则TestString与空字符串相比较.

'-d'(目录)
将TestString视为一个路径名并测试它是否为一个存在的目录

'-f'(常规文件)
将TestString视为一个路径名并测试它是否为一个存在的常规文件.

'-s'非空的常规文件
将TestString视为一个路径名称并测试它是否是一个存在的,尺寸大于0的常规文件

-l 符号连接
将TestString视为一个路径名并测试他是否是一个存在的符号连接

-x可执行
将TestString视为一个路径名,并测试它是否为一个存在的,具有可执行权限的文件.该权限是由操作系统检测.

-f 对子请求存在的文件
检查TestString是否为一个有效的文件,而且可以在服务器当前的访问控制配置下被访问的.它使用一个内部子请求做检查,由于会降低服务器的性能,所以谨慎使用

-U(对子请求存在的URL)
检查TestString是否是一个有效的URL,而且可以在服务器当前的访问控制配置下访问.它使用一个内部子请求来做检查,由于会降低服务器的性能.所以谨慎使用.

//notice
所有这些测试都可以用惊叹号做前缀(!)以实现测试条件的反转
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
还可以在CondPattern之后追加特殊的标记[flag]作为RewriteCond指令的第三个参数.flags是一个以逗号分隔的以下标记的列表.

'nocase|NC'(忽略大小写)
它是测试大小写,扩展后的TestString和CondPattern中的'A-Z'和'a-z'是没有区别的.此标记仅用于TestString和CondPattern的比较,而对文件系统和子请求的检查不起作用.

'ornext|OR'(或下一个条件)
他以OR方式组合若干规则的条件,而是隐含的AND.典型的例子:

RewriteCond %{REMOTE_HOST} ^host1.* [OR]
RewriteCond %{REMOTE_HOST} ^host2.* [OR]
RewriteCond %{REMOTE_HOST} ^host3.*
RewriteRule ....针对这三个主机的规则集合

举例:
如果按照请求的"User-Agent:"重写一个站点的主页,可以这样写:

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]
解释:
如果你使用的浏览器的标志是'Mozilla',则你得到内容最大化的主页(含有Frames等等).如果你使用的是(基于终端的)Lynx,则你得到的是内容最小化的主页(不含table等等).如果上述条件都不满足(使用的是其他浏览器),则你得到的是一个标准的主页.

+----------------------------------------------------------------------------------------+
+----------------------------------------------------------------------------------------+
+----------------------------------------------------------------------------------------+
RewriteEngine指令
说明:打开或者关闭运行时的重写引擎
语法:RewriteEngine on|off
默认值:RewriteEngine off
作用域:server config, virtual host,directory,.htaccess
覆盖项:FileInfo
状态:扩展(E)
模块:mod_rewrite

RewriteEngine指令打开或关闭运行时的重写引擎.如果设置为off,则此模块在运行时不执行任何重写操作,同时也不更新SCRIPT_URx环境变量.

使用该指令可以使此模块无效,则无需注释所有的RewriteRule指令!

注意:默认情况下,重写配置是不可继承的,也就是必须在每个需要使用重写引擎的虚拟主机中设置一个RewriteEngine on指令.

+----------------------------------------------------------------------------------------+
RewriteLock指令:
说明:设置RewriteMap同步使用的锁定文件名
语法:RewriteLock file-path
作用域:server config
状态:扩展(E)
模块:mod_rewrite

此指令设置mod_rewrite为了和RewriteMap程序通讯而使用的同步锁机制.在需要使用重写映射表程序(rewriting map-program)时,它必须是一个本地路径(而不能是一个NFS挂接设备).对其他类型的重写映射表,则无此要求.

+-----------------------------------------------------------------------------------------+
RewriteLog指令:
设置重写引擎日志的文件名:
语法:RewriteLog file-path
作用域:server config,virtual host
状态:扩展(E)
模块:mod_rewrite

RewriteLog指令设置用于记录所有重写操作的日志文件的名称.如果此文件名不以斜杠('/')开头,则它是相对于Server Root的.此指令应该在每个服务器级别配置中仅仅出现一次.

如果要关闭对重写操作的记录,不推荐将Filename设置为/dev/null,因为,虽然重写引擎不能输出记录了,但仍会在内部建立这个日志文件,这样会使服务器速度降低,而且对管理员毫无益处.要关闭日志,可以删除注释或注解RewriteLog指令,或者使用"RewriteLogLevel 0"的设置

RewriteLog "/usr/local/var/apache/logs/rewrite.log"

+-----------------------------------------------------------------------------------------+

 

 

 

posted @ 2012-09-27 15:34  sgsheg  阅读(209)  评论(0编辑  收藏  举报