Apache HTTP 服务器版本 2.5

本文档是 mod_rewrite
参考文档的补充。
它提供了一些使用 mod_rewrite 的高级技术。
一种分配服务器负载或存储空间的常见技术称为"分片"。 使用此方法时,前端服务器将使用 URL 将用户或对象一致地"分片"到 不同的后端服务器。
在外部映射文件中维护从用户到目标服务器的映射。 它们看起来像:
user1 physical_host_of_user1
user2 physical_host_of_user2
# ... and so on
我们将其放入 map.users-to-hosts 文件。
目标是映射:
/u/user1/anypath
到
http://physical_host_of_user1/u/user/anypath
这样每个 URL 路径不需要在每个后端物理主机上都有效。 以下规则集借助映射文件为我们完成此操作, 假设 server0 是在用户在映射中没有条目时使用的默认服务器:
RewriteEngine on
RewriteMap users-to-hosts "txt:/path/to/map.users-to-hosts"
RewriteRule "^/u/([^/]+)/?(.*)" "http://${users-to-hosts:$1|server0}/u/$1/$2"
请参阅 RewriteMap
文档和 RewriteMap 指南
以了解此指令语法的更多讨论。
我们希望动态生成内容,但一旦生成就将其静态存储。 此规则将检查静态文件是否存在,如果不存在,则生成它。 静态文件可以定期删除(例如通过 cron), 并在需要时按需重新生成。
# This example is valid in per-directory context only
RewriteCond "%{REQUEST_URI}" !-U
RewriteRule "^(.+)\.html$" "/regenerate_page.cgi" [PT,L]
-U 操作符确定测试字符串(在本例中为
REQUEST_URI)是否是有效的 URL。它通过子请求来完成。
如果此子请求失败——即请求的资源不存在——此规则将调用 CGI 程序
/regenerate_page.cgi,该程序生成请求的资源并将其保存到
文档目录中,这样下次请求时就可以提供静态副本了。
通过这种方式,不经常更新的文档可以以静态形式提供。 如果需要刷新文档,可以从文档目录中删除它们, 下次请求时将重新生成。
我们希望使用 mod_rewrite
在多台服务器之间随机分配负载。
我们将使用 RewriteMap 和服务器列表来实现。
RewriteEngine on
RewriteMap lb "rnd:/path/to/serverlist.txt"
RewriteRule "^/(.*)" "http://${lb:servers}/$1" [P,L]
serverlist.txt 将包含服务器列表:
## serverlist.txt
servers one.example.com|two.example.com|three.example.com
如果你希望某台特定服务器承担更多负载,可以在列表中多次添加它。
Apache 自带一个负载均衡模块 -
mod_proxy_balancer - 它比你使用
mod_rewrite 拼凑出来的任何方案都更加灵活和功能丰富。
一些拥有数千用户的站点使用结构化的主目录布局,
即每个主目录位于一个子目录中,
该子目录以用户名的第一个字符开头。因此,
/~larry/anypath 是
/home/l/larry/public_html/anypath,
而 /~waldo/anypath 是
/home/w/waldo/public_html/anypath。
我们使用以下规则集将波浪号 URL 展开为上述布局。
RewriteEngine on RewriteRule "^/~(([a-z])[a-z0-9]+)(.*)" "/home/$2/$1/public_html$3"
默认情况下,重定向到 HTML 锚点不起作用,因为
mod_rewrite 会转义 # 字符,
将其变为 %23。这反过来会破坏重定向。
在 RewriteRule 上使用 [NE] 标志。
NE 代表不转义(No Escape)。
mod_rewrite
默认会进行 URL 编码的其他特殊字符。我们希望使用 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" [L]
RewriteRule "^foo\.html$" "foo.night.html"
这将在 07:01-18:59 时间段内,以 URL
foo.html 提供 foo.day.html 的内容,
在其余时间提供 foo.night.html 的内容。
mod_cache、中间代理和浏览器
可能各自缓存响应,导致在配置的时间窗口之外显示某个页面。
可以使用 mod_expires 来控制此效果。
当然,动态提供内容并根据时间自定义它是更好的方式。有时,我们希望在执行重写时保持某种状态。例如, 你想记录你已完成该重写,以便稍后检查请求是否通过该重写。 一种方法是设置环境变量。
使用 [E] 标志设置环境变量。
RewriteEngine on RewriteRule "^/horse/(.*)" "/pony/$1" [E=rewritten:1]
稍后在你的规则集中,你可以使用 RewriteCond 检查此环境变量:
RewriteCond "%{ENV:rewritten}" =1
请注意,环境变量在外部重定向后不会保留。你可以考虑使用 [CO] 标志来设置 cookie。对于目录级和 htaccess 重写, 当最终替换作为内部重定向处理时,上一轮重写的环境变量会以 "REDIRECT_" 为前缀。