zencart伪静态示例
[root@webhosting6 public_html]# cat htaccess_sample
##### NOTE: Replace /shop/ with the relative web path of your catalog in the "Rewrite Base" line below:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /shop/
# From Ultimate SEO URLs
RewriteRule ^(.*)-p-(.*).html$ index/.php?main_page=product_info&products_id=$2&%{QUERY_STRING} [L]
RewriteRule ^(.*)-c-(.*).html$ index/.php?main_page=index&cPath=$2&%{QUERY_STRING} [L]
RewriteRule ^(.*)-m-([0-9]+).html$ index/.php?main_page=index&manufacturers_id=$2&%{QUERY_STRING} [L]
RewriteRule ^(.*)-pi-([0-9]+).html$ index/.php?main_page=popup_image&pID=$2&%{QUERY_STRING} [L]
RewriteRule ^(.*)-pr-([0-9]+).html$ index/.php?main_page=product_reviews&products_id=$2&%{QUERY_STRING} [L]
RewriteRule ^(.*)-pri-([0-9]+).html$ index/.php?main_page=product_reviews_info&products_id=$2&%{QUERY_STRING} [L]
RewriteRule ^(.*)-ezp-([0-9]+).html$ index/.php?main_page=page&id=$2&%{QUERY_STRING} [L]
# For Open Operations Info Manager
RewriteRule ^(.*)-i-([0-9]+).html$ index/.php?main_page=info_manager&pages_id=$2&%{QUERY_STRING} [L]
# For dreamscape's News & Articles Manager
RewriteRule ^news/?$ index/.php?main_page=news&%{QUERY_STRING} [L]
RewriteRule ^news/rss.xml$ index/.php?main_page=news_rss&%{QUERY_STRING} [L]
RewriteRule ^news/archive/?$ index/.php?main_page=news_archive&%{QUERY_STRING} [L]
RewriteRule ^news/([0-9]{4})-([0-9]{2})-([0-9]{2}).html$ index/.php?main_page=news&date=$1-$2-$3&%{QUERY_STRING} [L]
RewriteRule ^news/archive/([0-9]{4})-([0-9]{2}).html$ index/.php?main_page=news_archive&date=$1-$2&%{QUERY_STRING} [L]
RewriteRule ^news/(.*)-a-([0-9]+)-comments.html$ index/.php?main_page=news_comments&article_id=$2&%{QUERY_STRING} [L]
RewriteRule ^news/(.*)-a-([0-9]+).html$ index/.php?main_page=news_article&article_id=$2&%{QUERY_STRING} [L]
# All other pages
# Don't rewrite real files or directories
RewriteCond %{REQUEST_FILENAME} !-f [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*).html$ index/.php?main_page=$1&%{QUERY_STRING} [L]
伪静态资料:
Apache模块 mod_rewrite
说 明 一个基于一定规则的实时重写URL请求的引擎
状 态 扩展(E)
模 块名 rewrite_module
源 文件 mod_rewrite.c
兼 容性 仅在 Apache 1.3 及以后的版本中可用
概述
此模块提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规
则以及附加条件规则 的灵活而且强大的URL操作机制。此URL操作可以依赖于各种测试,比如服务器变量、环境变量、
HTTP头、时间标记,甚至各种格式的用于匹配URL组成 部分的查找数据库。
此模块可以操作URL的所有部分(包括路径信息部分),在服务器级的(httpd.conf)和目录级的(.htaccess) 配置都有效,
还可以生成最终请求字符串。此重写操作的结果可以是内部子处理,也可以是外部请求的转向,甚至还可以是内部代理处
理。
但是,所有这些功能和灵活性带来一个问题,那就是复杂性,因此,不要指望一天之内就能看懂整个模块。
更多的讨论、细节、示例,请查看详细的URL 重写文档 。
特殊字符的引用
在Apache 1.3.20中,TestString和Substitution中的特殊字符 可以用前导斜杠(/)来实现转义(即忽略其特殊含义而视之为普通
字符)。 比如,Substitution可以用"/$" 来包含一个美元符号,以避免mod_rewrite把它视为反向引用。
环境变量
此模块会跟踪两个额外的(非标准)CGI/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
语 法 RewriteBase URL-path
默 认值 参见使用方法
作 用域 directory, .htaccess
覆 盖项 FileInfo
状 态 扩展(E)
模 块 mod_rewrite
RewriteBase指令显式地设置了目录级重写的基准URL。在 下文中,你将看到RewriteRule 可 以用于目录级的配置
文件中(.htaccess)并在局部范围内起作用,即规则实际处理的只是剥离了本地路径前缀的一部分。处 理结束后,这个
路径会被自动地附着回去。默认值是"RewriteBase physical-directory-path"。在对一个新的URL进行替换时,此模块必须把这个URL重新注入到服务器处理中。为此,它必须知道其对应的URL前缀
或者说URL基 准。通常,此前缀就是对应的文件路径。但是,大多数网站URL不是直接对应于其物理文件路径的,因而
一般不能做这样的假定! 所 以在这种情况下,就必须用RewriteBase指令来指定正确的URL前缀。
如果你的网站服务器URL不是与物理文件路径直接对应的,你必须在每个使用RewriteRule 的.htaccess文 件中使用
RewriteBase指令。
例如,目录级配置文件内容如下:
# /abc/def/.htaccess -- /abc/def 目录的配置文件
# 注意:/abc/def 是 /xyz 的物理路径(例如存在一条'Alias /xyz /abc/def'指令)。
RewriteEngine On
# 让服务器知道我们使用的是 /xyz 而不是物理路径 /abc/def
RewriteBase /xyz
# 重写规则
RewriteRule ^oldstuff/.html$ newstuff.html
上述例子中,对/xyz/oldstuff.html的请求被正确地重写为对物理文件/abc/def/newstuff.html的 请求。
仅供Apache Hacker们参考
以下列出了内部处理的详细步骤:
请求:
/xyz/oldstuff.html
内部处理过程:
/xyz/oldstuff.html -> /abc/def/oldstuff.html (per-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)
结果:
/abc/def/newstuff.html
虽然这个过程看来很繁复,但是由于目录级重写的到来时机已经太晚了,它不得不把这个(重写)请求重新注入到 Apache核
心中,所以Apache内部确实是这样处理的。但是:它的开销并不象看起来的那样大,因为重新注入完全在Apache服务器
内部进行,而且 这样的过程在Apache内部也为其他许多操作所使用。所以,你可以充分信任其设计和实现是正确的。
RewriteCond 指 令
说 明 定义重写发生的条件
语 法 RewriteCond TestString CondPattern [flags]
作 用域 server config, virtual host, directory, .htaccess
覆 盖项 FileInfo
状 态 扩展(E)
模 块 mod_rewrite
RewriteCond指令定义了规则生效的条件,即在一个RewriteRule 指 令之前可以有一个或多个RewriteCond指令。
条件之后的重写规则仅在当前URI 与Pattern匹配并且满足此处的条件(TestString能够与CondPattern匹 配)时才会起作用。
TestString是一个纯文本的字符串,但是还可以包含下列可扩展的成分:
• RewriteRule反向引用 ,引用方法是:
$N
(0 <= N <= 9)引用当前(带有若干RewriteRule指令的)RewriteCond中 的与Pattern匹配的分组成分(圆括号!)。
• RewriteCond反向引用 ,引用方法是: %N
(1 <= N <= 9)引用当前若干RewriteCond条件中最后符合的条 件中的分组成分(圆括号!)。
• RewriteMap扩展 ,引用方法是:
${mapname:key|default}
细节请参见RewriteMap 指令 。
• 服务器变量 ,引用方法是:
%{NAME_OF_VARIABLE}
NAME_OF_VARIABLE可以是下表列出的字符串之一:
HTTP头 连接与请求
HTTP_USER_AGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_ACCEPT
REMOTE_ADDR
REMOTE_HOST
REMOTE_PORT
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPE
服务器自身 日期和时间 其它
DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_ADDR
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIME
API_VERSION
THE_REQUEST
REQUEST_URI
REQUEST_FILENAME
IS_SUBREQ
HTTPS
这些变量都对应于类似命名的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的版本(比如在Apache 1.3.14的发行版中这个值是
19990320:10)。 通常,对它感兴趣的是模块的开发者。
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
结 构中的uri字段)的一个副本。
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匹配。
注意:CondPattern是一个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,而且可以在服务器当前的访问控制配置下被访问。它使用一个
内部子请求来做检查,由于会降低服务器的性能,所以请谨慎使用!
注意
所有这些测试都可以用惊叹号作前缀('!')以实现测试条件的反转。
3. 还可以在CondPattern之后追加特殊的标记[flags]作 为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 ... 针对这3个主机的规则集 ...
如果不用这个标记,你就必须要书写三次条件/规则对。
举例
如果要按请求头中的"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挂接设备)。对其他类型的重写映射表(rewriting
map),则无此要求。
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"
RewriteLogLevel 指令
说 明 设置重写日志的详细程度
语 法 RewriteLogLevel Level
默 认值 RewriteLogLevel 0
作 用域 server config, virtual host
状 态 扩展(E)
模 块 mod_rewrite
RewriteLogLevel指令设置重写引擎日志的详细程度的级 别。0(默认级别)意味着不记录,而9或更大的值意味着记录
所有操作。
要关闭重写引擎日志,可以简单地将Level设为0,以关闭所有重写操作的记录。
较高的Level值会使Apache服务器速度急剧下降!大于2的Level值 只用于调试目的!
示例
RewriteLogLevel 3
RewriteMap 指令
说 明 定义用于关键词查找的映射函数
语 法 RewriteMap MapName MapType:MapSource
作 用域 server config, virtual host
状 态 扩展(E)
模 块 mod_rewrite
兼 容性 Apache 2.0.41 及以后的版本中可以使用不同的dbm类型
RewriteMap指令定义了一个映射表(Rewriting Map),映射函数将使用该表来查找关键字然后插入/替换字段。此查找操作
的源可以是多种类型。
MapName是映射表的名称,指定了一 个映射函数,用于重写规则的字符串替换,它可以是下列形式之一:
${MapName:LookupKey}
${MapName:LookupKey|DefaultValue}
如果使用了这样的形式,则会在MapName中查找关键词LookupKey。如果找到了,则被 替换成SubstValue; 如果没有找
到,则被替换成DefaultValue,如果没有指定DefaultValue, 则被替换成空字符串。
例如,你可能定义这样一个RewriteMap:
RewriteMap examplemap txt:/path/to/file/map.txt
然后你就可以像下面这样在RewriteRule中使用该映射:
RewriteRule ^/ex/(.*) ${examplemap:$1}
可以使用下列MapType和MapSource的组合:
• 标准纯文本
MapType: txt, MapSource: 有效的Unix文件系统文件名 这是重写映射表的标准形式。MapSource是一个纯文本文件,包含空行、注释行(以字符'#'打头), 以及每行一个
的替换对,如下所示:
MatchingKey SubstValue
例子
## 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
• 随机纯文本
MapType: rnd, MapSource: 有效的Unix文件系统文件名
这个与上述的标准纯文本很相似,但它有一个特殊的后处理特性:查找完毕后,会解析其中包含的"|" 符号(含义
为"或")。 也就是说,会随机地选择其中之一作为返回值。虽然这看似毫无意义,但设计它的意图是在一个查找
值是服务器名称的反向代理环境中实现负载平衡。
例子
映射文件
## map.txt -- rewriting map
static www1|www2|www3|www4
dynamic www5|www6
配置指令
RewriteMap servers rnd:/path/to/file/map.txt
RewriteRule ^/(.*/.(png|gif|jpg)) http://${servers:static}/$1 [NC,P,L]
RewriteRule ^/(.*) http://${servers:dynamic}/$1 [P,L]
• 散列文件
MapType: dbm[=type], MapSource: 有效的Unix文件系统文件名
这里的源是一个二进制格式的DBM文件,包含了与纯文本相同的内容,但是因为它有优化了的特殊表现形式,
使 它的查找速度明显快得多。 此type可以是sdbm, gdbm, ndbm, db(由编译时配置决 定)。如果省略type,则使用
编译时选择的缺省值。 你可以使用任何DBM工具或者下列Perl脚本来创建这个文件,但必须保证DBM的类型
正确。建立NDBM文件的例子如下:
#!/path/to/bin/perl
##
## txt2dbm -- 将 txt 映射表转换为 dbm 格式
##
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 (<TXT>) {
next if (/^/s*#/ or /^/s*$/);
$DB{$1} = $2 if (/^/s*(/S+)/s+(/S+)/);
}
untie %DB;
close(TXT);$ txt2dbm map.txt map.db
• 内部函数
MapType: int, MapSource: Apache内部函数
这里的源是一个Apache的内部函数。目前,还不能由你自己建立,只能使用下列已经存在的函数:
• toupper:
转换查找关键词为大写
• tolower:
转换查找关键词为小写
• escape:
转换查找关键词中的特殊字符为十六进制编码
• unescape:
转换查找关键词中的十六进制编码为特殊字符
• 外部的重写程序
MapType: prg, MapSource: 有效的Unix文件系统文件名
这里的源是一个程序,而不是一个映射表文件。程序设计语言可以随意选择,但最终结果必须是可执行的(或者是
目标代码,或者是首 行为'#!/path/to/interpreter'的脚本)。
此程序仅在Apache服务器启动时启动一次,随后通过stdin和stdout文 件句柄与重写引擎交互。 对每个映
射函数的查找操作,它从stdin接收以回车结束的查找关键词,然后把查找的结果以回车结束 反馈到
stdout,如果查找失败,则返回四个字符的字符串"NULL"(对给定的关键词没有对应的值)。此程序的最简单形
式 是一个1:1的映射(即:key == value),例如:
#!/usr/bin/perl
$| = 1;
while (<STDIN>) {
# ...在这里放置转换和查找...
print $_;
}
但是必须注意:
• "简单就是美"(KISS: Keep it simple, stupid!)。此程序的崩溃会直接导致Apache服务器的崩溃。
• 绝不要对stdout做I/O缓冲(一个常见的错误),它会导致死循环!所以上述例子中才会 使用"$|=1"来
预防。
• 使用RewriteLock 指 令定义一个锁文件,用于同步mod_rewrite和此程序之间的通讯。默认是没有同
步操作的。
RewriteMap指令可以多次出现。对每个映射函数都可以使用一 个RewriteMap指令来定义其重写映射表。虽然不能在
目录上下文(per- directory context)中定义映射表,但是完全可以在其中使用映射 表。
注意
对于纯文本和DBM格式的文件,已经查找过的关键词会被缓存在内核中,直到映射表的mtime改变了或者服务器重启了。
这样, 你可以把每个请求都会用到的映射函数放在规则中,这是没有问题的,因为外部查找只进行一次。
RewriteOptions 指令
说 明 为重写引擎设置一些特殊的选项
语 法 RewriteOptions Options
作 用域 server config, virtual host, directory, .htaccess
覆 盖项 FileInfo
状 态 扩展(E)
模 块 mod_rewrite
兼 容性 MaxRedirects在2.1及以后的版本中已经不可用
RewriteOptions指令为当前服务器级和目录级的配置设置 一些选项。Option当前仅可以是如下值:
inherit 此值强制当前配置继承其父配置。在虚拟主机级配置中,它意味着主服务器的映射表、条件和规则可以被继承。在
目录级配置中,它意味着其 父目录的.htaccess中的条件和规则可以被继承。
RewriteRule 指 令
说 明 为重写引擎定义重写规则
语 法 RewriteRule Pattern Substitution [flags]
作 用域 server config, virtual host, directory, .htaccess
覆 盖项 FileInfo
状 态 扩展(E)
模 块 mod_rewrite
兼 容性 cookie-flag在Apache 2.0.40及以后的版本中可用
RewriteRule指令是重写引擎的根本。此指令可以多次使用。 每个指令定义一个简单的重写规则。这些规则的定义顺序
尤为重要——在运行时,规则是按这个顺序逐一生效的。
Pattern是一个作用于当前 URL的perl兼容的正则表达式。"当前URL"是指该规则生效时刻的URL的 值。它可能与被请
求的URL截然不同,因为其他规则可能在此之前已经发生匹配并对它做了改动。
正则表达式的一些用法示例:
文本
. 任意一个单字符
[chars] 字符类: "chars"中的任意一个字符
[^chars] 字符类: 不在"chars"中的字符
text1|text2 选择: text1 或 text2
量词
? 前面的字符出现 0 或 1 次
* 前面的字符出现 0 或 N 次(N > 0)
+ 前面的字符出现 1 或 N 次(N > 1)
分组
(text) text 组
(常用于设置一个选择的边界,或用于生成后引用:
在RewriteRule中可以用 $N 引用第N个分组)
锚
^ 锚定到行首
$ 锚定到行尾
转义
/c 对给定的字符c进行转义
(比如对".[]()"进行转义,等等)
更多有关正则表达式的资料请参见perl正则表达式手册页("perldoc perlre")。 另外,在mod_rewrite中,还可以使用否字符
('!')前缀实现反转。比如:"如果当前URL不与 模式相匹配"它用于使用否定式匹配模式较容易描述的某些情况,或者作为
最后一条规则。
注意
使用否字符以反转匹配模式时,匹配模式中不能使用分组的通配成分。由于模式不匹配而使分组的内容是空的,所以它是
不可能实现的。 因此,如果使用了否定式匹配模式,那么后继的字符串中就不能使用$N
重写规则中的Substitution是当原始URL与Pattern相 匹配时,用来替代(或替换)的字符串。除了纯文本,还可以包含:
1. 对Pattern的反向引用($N)
2. 对最后匹配的RewriteCond的反向引用(%N)
3. 规则条件测试字符串(%{VARNAME})中的服务器变量
4. 映 射函数 调用(${mapname:key|default}) 反向引用的$N(N=0..9)是 指用Pattern匹配的第N组的内容去替换URL。服务器变量与RewriteCond指 令的TestString
相同。映射函数由RewriteMap指令决定,其说明也参见该指令。这三种类型 变量按上面列表中的顺序被展开。
如上所述,所有的重写规则都是按配置文件中的定义顺序作用于Substitution的。URL被Substitution完 全替换,并继续处
理直到所有规则处理完毕,除非用L标记显式地终结(见 下文)。
'-'是一个特殊的替换串,意思是不替换。它可以用于仅 仅匹配某些URL而无须替换的情况,比如,在发生替换前,允许
以C(chain)标记连接的多个匹 配模式同时起作用。
此外,在Substitution之后还可以追加[flags]标 记作为RewriteRule指令的第三个参数。Flags是一个包含以逗号分隔的
下列标记的列表:
• 'chain|C'(链接下一规则)
此标记使当前规则与下一个规则相链接。它产生这样的效果:如果一个规则被匹配,则继续处理其后继规则,也
就是这个标记不起作用;如果该规则不被 匹配,则其后继规则将被跳过。比如,在一个目录级规则中执行一个外
部重定向时,你可能需要删除".www"(此处不应该出现".www")。
• 'cookie|CO=NAME:VAL:domain[:lifetime[:path]]'(设 置cookie)
在客户端设置一个cookie。cookie的名称是NAME,值是VAL。domain是 该cookie的域,比如'.apache.org',可选
的lifetime是cookie的有效期(分钟),可选的path是 cookie的路径。
• 'env|E=VAR:VAL'(设 置环境变量)
此标记将环境变量VAR的值为VAL,VAL可以包含可扩展的正则表达式反向引 用($N和%N)。此标记可以多次使
用以设置多个变量。这些变量可以在其后许多情况下被间接引用, 通常是在XSSI(<!--#echo var="VAR"--
>)或CGI($ENV{'VAR'}) 中,也可以在后继的RewriteCond指令的CondPattern参 数中通过%{ENV:VAR}引用。
使用它可以记住从URL中剥离的信息。
• 'forbidden|F'(强制禁止URL)
强制禁止当前URL,也就是立即反馈一个HTTP响应码403(被禁止的)。使用这个标记,可以链接若干个
RewriteConds来有条件地阻塞某些 URL。
• 'gone|G'(强制废弃URL)
强制当前URL为已废弃,也就是立即反馈一个HTTP响应码410(已废弃的)。使用这个标记,可以标明页面已经
被废弃而不存在了。
• 'handler|H=Content-handler'(强 制指定内容处理器)
强自制定目标文件的内容处理器为Content-handler。例如,用来模拟mod_alias 模 块的ScriptAlias 指 令,
以强制映射文件夹内的所有文件都由"cgi-script"处理器处理。
• 'last|L'(结尾规则)
立即停止重写操作,并不再应用其他重写规则。它对应于Perl中的last命令或C语言中的break命 令。这个
标记用于阻止当前已被重写的URL被后继规则再次重写。例如,使用它可以重写根路径的URL('/')为实际存在的
URL(比如:'/e/www/')。
• 'next|N'(从头再来)
重新执行重写操作(从第一个规则重新开始)。此时再次进行处理的URL已经不是原始的URL了,而是经最后一个
重写规则处理过的URL。它对应于Perl 中的next命令或C语言中的continue命令。此标记可以重新开始重写
操作(立即回到循环的 开头)。但是要小心,不要制造死循环!
• 'nocase|NC'(忽略大小写)
它使Pattern忽略大小写,也就是在Pattern与当前URL匹配时,'A-Z'和'a- z'没有区别。
• 'noescape|NE'(在输出中不对URI进行转义)
此标记阻止mod_rewrite对重写结果应用常规的URI转义规则。 一般情况下,特殊字符('%', '$', ';'等)会被转义为等
值的十六进制编码('%25', '%24', '%3B'等)。此标记可以阻止这样的转义,以允许百分号等符号出现在输出中,比如:
RewriteRule /foo/(.*) /bar?arg=P1/%3d$1 [R,NE]
可以使'/foo/zed转向到一个安全的请求'/bar?arg=P1=zed'。
• 'nosubreq|NS'(不对内部子请求进行处理)
在当前请求是一个内部子请求时,此标记强制重写引擎跳过该重写规则。比如,在mod_include 试 图搜索目录
默认文件(index.xxx)时,Apache会在内部产生子请求。对于子请求,重写规则不一定有用,而且如果整 个规
则集都起作用,它甚至可能会引发错误。所以,可以用这个标记来排除某些规则。
使用原则:如果你为URL添加了CGI脚本前缀,以强制它们由 CGI脚本处理,但对子请求处理的出错率(或者资
源开销)很高,在这种情况下,可以使用这个标记。
• 'proxy|P'(强制为代理)
此标记使替换成分被内部地强制作为代理请求发送,并立即中断重写处理,然后把处理移交给mod_proxy 模 块。
你必须确保此替换串是一个能够被mod_proxy 处 理的有效URI(比如以http://hostname开头),否则将得到一个代理模块返回的错误。使用这 个标记,可以把某些远程成分映射到本地服务器域名空间,从而增强了ProxyPass
指 令的功能。
注意:要使用这个功能,必须已经启用了mod_proxy 模 块。
• 'passthrough|PT'(移交给下一个处理器)
此标记强制重写引擎将内部request_rec结构中的uri字段设置为filename字 段的值,这个小小的修改使
得RewriteRule指令的输出能够被(从URI转换到文件名的)Alias, ScriptAlias, Redirect等指令进行后续
处理[原文:This flag is just a hack to enable post-processing of the output of RewriteRule directives, using Alias,
ScriptAlias, Redirect, and other directives from various URI-to-filename translators.]。举一个能说明其含义的例
子: 如果要将/abc重写为/def, 然后再使用mod_alias 将/def转 换为/ghi,可以这样:
RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi
如果省略了PT标记,虽然将uri=/abc/...重写为filename=/def/...的 部分运作正常,但是后续的
mod_alias在试图将URI转换到文件名时会遭遇失效。
注意:如果需要混合使用多个将URI转换到文件名的模块时,就必须使用这个标记。。此处混 合使用
mod_alias 和mod_rewrite 就 是个典型的例子。
• 'qsappend|QSA'(追加查询字符串)
此标记强制重写引擎在已有的替换字符串中追加一个查询字符串,而不是简单的替换。如果需要通过重写规则在
请求串中增加信息,就可以使用这个标记。
• 'redirect|R [=code]'(强 制重定向)
若Substitution以http://thishost[:thisport]/(使 新的URL成为一个URI)开头,可以强制性执行一个外
部重定向。如果没有指定code,则产生一个HTTP响应码302(临时性移 动)。如果需要使用在300-400范围内的其
他响应代码,只需在此指定即可(或使用下列符号名称之一:temp(默认), permanent, seeother)。使用它可以
把规范化的URL反馈给客户端,如将"/~"重写为"/u/", 或始终对/u/user加上斜杠,等等。
注意:在使用这个标记 时,必须确保该替换字段是一个有效的URL。否则,它会指向一个无效的位置!并且要
记住,此标记本身只是对URL加上http://thishost[:thisport]/前 缀,重写操作仍然会继续进行。通常,
你还会希望停止重写操作而立即重定向,那么就还需要使用'L'标记。
• 'skip|S=num'(跳过后继规则)
此标记强制重写引擎跳过当前匹配规则之后的num个规则。它可以模拟if-then-else结构:最后一个规则是 then从
句,而被跳过的skip=N个规则是else从句。注意:它和'chain|C'标记是不同的!
• 'type|T=MIME-type'(强制 MIME类型)
强制目标文件的MIME 类型 为MIME-type,可以用来基于某些特定条件强制设置内容类 型。比如,下面的指令可
以让.php文件在以.phps扩展名调用的情况下由mod_php按 照PHP源代码的MIME类型(application/x-httpd-
php-source)显示:
RewriteRule ^(.+/.php)s$ $1 [T=application/x-httpd-php-source]
目录级重写
为了在.htaccess 文 件中针对特定目录使用重写引擎,你必须同时设置"RewriteEngine On"和"Options
FollowSymLinks"。如果管理员禁止了该目录的FollowSymLinks特性,重写引擎将不 会工作,这样做的原因是处于
安全方面的考虑。
在服务器级配置中,模式匹配是作用于整个URL的。但是在目录级配置文件.htaccess中使用重写引擎的时候,目录 前
缀(一般总是和特定的目录名称相同)将会在模式匹配前被自动移除并在替换完成后被自动添加回去。这个特性对于重写 来
说是非常重要的,否则你就被迫必须总是对父目录进行匹配,而这并不总是可行的。这里有一个例外:如果替换字符串
以"http://" 开头,则不会添加目录前缀,而是强制执行一个外部重定向或代理操作(如果使用了P标 志的话)。参见
RewriteBase 指 令以获得更多信息。
还可以在<Directory>配 置段中使用重写引擎,前缀匹配规则与在.htaccess中使用重写引擎时完全相同,并且这种
做法更加简单。然而,为了避免前 缀替换复杂化,我们还是建议尽量将重写规则放置在主服务器或虚拟主机配置部分,而
不是放置在<Directory>配 置段中。
虽然重写规则在语法上允许放置在<Location>配 置段中,但这不是必须的,并且我们也反对这样做。
注意:绝对URL的替换
当替换字段以"http://thishost[:thisport]"作为前缀时,mod_rewrite 会 将它自动剥离出去。在配合生成主机
名部分的映射函数使用的时候,这个对隐含的外部重定向URL的简化操作是有用的而且是重要的。下面的第一个例子有助于理 解这点。
谨记:由于此功能的存在,以"http://thishost" 为前缀的无条件外部重定向到自身所在的服务器是无效的。要实现一
个到自身的重定向,必须使用R标记。
注意:查询字符串
Pattern不会按照查询字符串进行匹配。为了达到这个目的,你必须使用一个带有%{QUERY_STRING}变 量的
RewriteCond 指 令。当然,你也可以在替换字符串中创建包含查询字符串的URL:在替换字符串串中使用问号,以标明
其后的部分应该被重新注入到QUERY_STRING 中。而要删除一个已有的请求串,则可以用问号来终结替换字符串。为了
联合新旧查询字符串,请使用[QSA]标志。
以下是所有可能的替换组合及其含义:
在服务器级配置中(httpd.conf)
对给定的请求"GET /somepath/pathinfo":
给定的规则 得到的替换字符串
---------------------------------------------- ----------------------------------
^/somepath(.*) otherpath$1 非法,不被支持
^/somepath(.*) otherpath$1 [R] 非法,不被支持
^/somepath(.*) otherpath$1 [P] 非法,不被支持
---------------------------------------------- ----------------------------------
^/somepath(.*) /otherpath$1 /otherpath/pathinfo
^/somepath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo
通过外部重定向
^/somepath(.*) /otherpath$1 [P] 毫无意义,不被支持
---------------------------------------------- ----------------------------------
^/somepath(.*) http://thishost/otherpath$1 /otherpath/pathinfo
^/somepath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo
通过外部重定向
^/somepath(.*) http://thishost/otherpath$1 [P] 毫无意义,不被支持
---------------------------------------------- ----------------------------------
^/somepath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo
通过外部重定向
^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
通过外部重定向
([R]标记是多余的)
^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
通过内部代理
在/somepath的目录级配置中
(也就是/physical/path/to/somepath/.htacccess文件中含有:RewriteBase /somepath)
对给定的请求"GET /somepath/localpath/pathinfo":
给定的规则 得到的替换字符串
---------------------------------------------- ----------------------------------
^localpath(.*) otherpath$1 /somepath/otherpath/pathinfo
^localpath(.*) otherpath$1 [R]
http://thishost/somepath/otherpath/pathinfo
通过外部重定向
^localpath(.*) otherpath$1 [P] 毫无意义,不被支持
---------------------------------------------- ----------------------------------
^localpath(.*) /otherpath$1 /otherpath/pathinfo
^localpath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo
通过外部重定向^localpath(.*) /otherpath$1 [P] 毫无意义,不被支持
---------------------------------------------- ----------------------------------
^localpath(.*) http://thishost/otherpath$1 /otherpath/pathinfo
^localpath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo
通过外部重定向
^localpath(.*) http://thishost/otherpath$1 [P] 毫无意义,不被支持
---------------------------------------------- ----------------------------------
^localpath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo
通过外部重定向
^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
通过外部重定向
([R]标记是多余的)
^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
通过内部代理
初级URL重写指南
本文是mod_rewrite 参 考文档 的补充材料。阐述在实际应用中如何解决网管所面临的基于URL的典型问题,并详细描
述了如何配置URL重写规则集以解决这些问题。
注意:根据你的服务器配置,有可能必须对这里的例子作些小修改,比如,在额外启用mod_alias 和mod_userdir 的
情况下要增加[PT]标志,或者为了适应目录级(.htaccess)的配置而将针对服务器级的规 则集进行重写。对一个特定的
规则集应该先透彻理解然后再考虑应用,这样才能避免出现问题。
规范化URL
描述:
在有些web服务器上,一个资源会拥有多个URL。在实际应用和发布中应该使用的是规范的URL,其他的则是简
写或者只在内部使用。无论用 户在请求中使用什么形式的URL,最终看见的都应该是规范的URL。
解决方案:
对所有不规范的URL执行一个外部HTTP重定向,以改变它在浏览器地址栏中的显示及其后继请求。下例中的规则
集用规范的/u/user替 换/~user,并修正了/u/user所遗漏的后缀斜杠。
RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R]
RewriteRule ^/u/([^/]+)$ /$1/$2/ [R]
规范化主机名
描述:
这个规则的目的是强制使用特定的主机名以代替其他名字。比如,你想强制使用www.example.com代 替
example.com,就可以在以下方案的基础上进行修改:
解决方案:
对运行在非80端口的站点
RewriteCond %{HTTP_HOST} !^fully/.qualified/.domain/.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1
[L,R]
对运行在80端口的站点
RewriteCond %{HTTP_HOST} !^fully/.qualified/.domain/.name [NC]RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]
移动过的DocumentRoot
描述:
通常,web服务器的DocumentRoot 直 接对应于URL"/",但是它常常不是处于最高的一级。比如,你希望访问
者在进入网站时首先进入/about/目 录。可以使用下面给出的规则集。
解决方案:
只需将"/"重定向到"/about/"即可:
RewriteEngine on
RewriteRule ^/$ /about/ [R]
也可以使用RedirectMatch 指 令解决问题:
RedirectMatch ^/$ http://example.com/e/www/
结尾斜杠问题
描述:
每个网管对引用目录的结尾斜杠问题都有一本苦经,如果遗漏了,服务器会产生一个错误,因为如果请求
是"/~quux/foo"而不是" /~quux/foo/",服务器就会去找一个叫foo的文件,而它是一个目录,所以就报错了。通常,
可以使用这个FAQ entry 里面提到的方法解决问题。但是有时候需要使用重写规则来解决问题,比如,在应用了许
多复杂的重写规则之后。
解决方案:
解决这个微妙问题的方案是让服务器自动添加后缀斜杠。为了达到目的,必须使用一个外部重定向,以使浏览器能
够正确地处理后继的请 求(比如对图片的请求)。如果仅仅执行一个内部重写,可能仅仅对目录页面有效,而对含有
相对URL的图片的页面无效,因为浏览器有请求内嵌目标的可能。比 如,如果不用外部重定向,
对/~quux/foo/index.html页面中的image.gif的 请求将变成对/~quux/image.gif的请求!所以,应该
这样写:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo$ foo/ [R]
又懒又疯狂的做法是把这些写入其宿主目录中的顶级.htaccess中:
RewriteEngine on
RewriteBase /~quux/
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]
但是这样一来会增加处理上的开销。
将用户主目录移动到不同web服务器
描述:
通常,许多网管在建立一个新的web服务器时,都会有这样的要求:重定向一个web服务器上的所有用户主目录到
另一个web服务 器。
解决方案:
很简单,在老的web服务器上重定向所有的"/~user/anypath"到"http://newserver/~user/anypath":
RewriteEngine on
RewriteRule ^/~(.+) http://newserver/~$1 [R,L]在多个目录中搜索页面
描述:
有时会有必要使web服务器在多个目录中搜索页面,对此,MultiViews或者其他技术无能为力。
解决方案:
编制一个明确的规则集以搜索目录中的文件:
RewriteEngine on
# 首先尝试在 dir1 中寻找,找到即停
RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir1/$1 [L]
# 然后尝试在 dir2 中寻找,找到即停
RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir2/$1 [L]
# 再找不到就继续寻找其他的 Alias 或 ScriptAlias 目录
RewriteRule ^(.+) - [PT]
按照URL的片段设置环境变量
描述:
希望保持请求之间的状态信息,又不希望使用CGI来包装所有页面,只是通过分离URL中的有用信息来做到。
解决方案:
可以用一个规则集来分离出状态信息,并设置环境变量以备此后用于XSSI或CGI。这样,一
个"/foo/S=java/bar/" 的URL会被解析为"/foo/bar/",而环境变量STATUS则被设置为"java"。
RewriteEngine on
RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]
虚拟用户主机
描述:
如果需要为用户username支持一个www.username.host.domain.com的 主页,但不在此机器上建虚拟主机,
而是仅用在此机器上增加一个DNS A记录的方法实现。
解决方案:
仅能对包含"Host: "头的HTTP/1.1请求实现。可以使用以下规则集内部地将
http://www.username.host.com/anypath重 写为/home/username/anypath
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www/.[^.]+/.host/.com$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^www/.([^.]+)/.host/.com(.*) /home/$1$2
为外来访问者重定向用户主目录
描述:
对不是来自本地域ourdomain.com的外来访问者的请求,重定向其用户主目录URL到另一个 web服务器
www.somewhere.com,有时这种做法也会用在虚拟主机的配置段中。
解决方案:
只须一个重写条件:
RewriteEngine on
RewriteCond %{REMOTE_HOST} !^.+/.ourdomain/.com$
RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]重定向锚
描述:
默认情况下,重定向到一个HTML锚是不可行的,因为'#'会被转义为'%23'。 This, in turn, breaks the redirection.
解决方案:
在RewriteRule指令中使用[NE]标志(不转义)。
依赖于时间的重写
描述:
在页面内容需要按时间的不同而变化的场合,比如重定向特定页面等,许多网管仍然采用CGI脚本的方法,如何用
mod_rewrite 来 实现呢?
解决方案:
有许多名为TIME_xxx的变量可以用在重写条件中,联合使用词典模式的"<STRING", "=STRING", ">STRING"比较,
就可以实现依赖于时间的重写:
RewriteEngine on
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule ^foo/.html$ foo.day.html
RewriteRule ^foo/.html$ foo.night.html
此例使foo.html在07:00-19:00时间内指向foo.day.html, 而在其余时间指向foo.night.html,对主
页是一个不错的功能...
对YYYY转变为XXXX的向前兼容
描述:
在转变了大批document.YYYY文件为document.XXXX后 (比如.html→.phtml),如何保持URL的向前兼容
(仍然虚拟地存在)?
解决方案:
只须按基准文件名重写,并测试带有新的扩展名的文件是否存在,如果存在则用新的,否则仍然用原来的。
# 将document.html重写为document.phtml的向后兼容的规则集
# 当且仅当document.phtml存在且document.html不存在的时候
RewriteEngine on
RewriteBase /~quux/
# 剪切并记住basename
RewriteRule ^(.*)/.html$ $1 [C,E=WasHTML:yes]
# 如果存在的话就重写为document.phtml
RewriteCond %{REQUEST_FILENAME}.phtml -f
RewriteRule ^(.*)$ $1.phtml [S=1]
# 否则返回先前的basename
RewriteCond %{ENV:WasHTML} ^yes$
RewriteRule ^(.*)$ $1.html
内容处理
从旧到新(内部)
描述:
假定已经把文件foo.html改名为bar.html,需要对老的 URL向后兼容,即让用户仍然可以使用老的URL,而
感觉不到文件被改名了。
解决方案:
通过以下规则内部地将老的URL重写为新的:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo/.html$ bar.html从旧到新(外部)
描述:
仍然假定已经把文件foo.html改名为bar.html,需要对老的 URL向后兼容,但是要让用户得到文件被改名的
暗示,即浏览器的地址栏中显示的是新的URL。
解决方案:
作一个HTTP的强制重定向以改变浏览器和用户界面上的显示:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo/.html$ bar.html [R]
从静态到动态
描述:
如何无缝转换静态页面foo.html为动态的foo.cgi,而不为浏 览器/用户所察觉。
解决方案:
只须重写此URL为CGI-script,并强制作为CGI-script运行的MIME类型。比如对/~quux/foo.html的 请求会执
行/~quux/foo.cgi 。
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo/.html$ foo.cgi [T=application/x-httpd-cgi]
访问控制
阻止Robot
描述:
如何阻止一个完全匿名的Robot取得特定网络区域的页面?/robots.txt文件可以包含若 干"Robot排除协议"行,
但不足以阻止此类Robot。
解决方案:
可以用一个规则集以拒绝对网络区域/~quux/foo/arc/(对一个很深的目录区域进行列表可 能会使服务器产生很
大的负载)的访问。还必须确保仅阻止特定的Robot,也就是说,仅仅阻止Robot访问主机是不够的(这样会同时阻止
用户访问该主 机)。为此,就需要对HTTP头的User-Agent信息作匹配。
RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR} ^123/.45/.67/.[8-9]$
RewriteRule ^/~quux/foo/arc/.+ - [F]
阻止内嵌的图片
描述:
假设http://www.quux-corp.de/~quux/有一些内嵌GIF图片的页面,这 些图片很好,所以就有人盗链到他
们自己的页面中了。由于这样徒然增加了我们服务器的流量,因此,我们不愿意这种事情发生。
解决方案:
虽然,我们不能100%地保护这些图片不被写入别人的页面,但至少可以对发出HTTP Referer头的浏览器加以限制。
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
RewriteRule .*/.gif$ - [F]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !.*/foo-with-gif/.html$
RewriteRule ^inlined-in-foo/.gif$ - [F]拒绝代理
描述:
如何拒绝某个主机或者来自特定主机的用户使用Apache代理?
解决方案:
首先,要确保在配置文件中mod_rewrite 位 于mod_proxy 之 后!使它在mod_proxy 之 前被调用。然后,使
用如下方法拒绝某个主机:
RewriteCond %{REMOTE_HOST} ^badhost/.mydomain/.com$
RewriteRule !^http://[^/.]/.mydomain.com.* - [F]
使用如下方法拒绝user@host-dependent用户:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost/.mydomain/.com$
RewriteRule !^http://[^/.]/.mydomain.com.* - [F]
其它
外部重写引擎
描述:
如何解决似乎无法用mod_rewrite 解 决的FOO/BAR/QUUX/之类的问题?
解决方案:
可以使用一个与RewriteMap 功 能相同的外部RewriteMap 程 序,一旦它在Apache启动时被执行,则从
STDIN接收被请求的URL ,并将处理过(通常是重写过的)的URL(以相同顺序)在STDOUT输出。
RewriteEngine on
RewriteMap quux-map prg:/path/to/map.quux.pl
RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1}
#!/path/to/perl
# 禁止使用会导致Apache陷入死循环的I/O缓冲
$| = 1;
# 从stdin读取URL(每行一个),并在stdout输出替换URL
while (<>) {
s|^foo/|bar/|;
print $_;
}
这是只是一个简单的示例,只是把所有的/~quux/foo/...重写为/~quux/bar/...而 已。但事实上,可以把它
修改成任何你想要的输出。但是要注意,虽然一般用户都可以使用,可是只有系统管理员才可以定 义这样的映射。