<-
Apache > HTTP 服务器 > 文档 > 版本 2.5 > Rewrite

mod_rewrite 高级技术

可用语言:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn 

本文档是 mod_rewrite 参考文档的补充。 它提供了一些使用 mod_rewrite 的高级技术。

请注意,这些示例中的许多不会在你的特定服务器配置中直接生效, 因此理解它们非常重要,而不仅仅是将示例复制粘贴到你的配置中。

参见

top

基于 URL 的跨多后端分片

描述:

一种分配服务器负载或存储空间的常见技术称为"分片"。 使用此方法时,前端服务器将使用 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 指南 以了解此指令语法的更多讨论。

top

即时内容再生成

描述:

我们希望动态生成内容,但一旦生成就将其静态存储。 此规则将检查静态文件是否存在,如果不存在,则生成它。 静态文件可以定期删除(例如通过 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,该程序生成请求的资源并将其保存到 文档目录中,这样下次请求时就可以提供静态副本了。

通过这种方式,不经常更新的文档可以以静态形式提供。 如果需要刷新文档,可以从文档目录中删除它们, 下次请求时将重新生成。

top

负载均衡

描述:

我们希望使用 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 拼凑出来的任何方案都更加灵活和功能丰富。

top

结构化用户目录

描述:

一些拥有数千用户的站点使用结构化的主目录布局, 每个主目录位于一个子目录中, 该子目录以用户名的第一个字符开头。因此, /~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"
top

重定向锚点

描述:

默认情况下,重定向到 HTML 锚点不起作用,因为 mod_rewrite 会转义 # 字符, 将其变为 %23。这反过来会破坏重定向。

解决方案:

RewriteRule 上使用 [NE] 标志。 NE 代表不转义(No Escape)。

讨论:
此技术当然也适用于 mod_rewrite 默认会进行 URL 编码的其他特殊字符。
top

基于时间的重写

描述:

我们希望使用 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 来控制此效果。 当然,动态提供内容并根据时间自定义它是更好的方式。
top

根据 URL 部分设置环境变量

描述:

有时,我们希望在执行重写时保持某种状态。例如, 你想记录你已完成该重写,以便稍后检查请求是否通过该重写。 一种方法是设置环境变量。

解决方案:

使用 [E] 标志设置环境变量。

RewriteEngine on
RewriteRule   "^/horse/(.*)"   "/pony/$1" [E=rewritten:1]

稍后在你的规则集中,你可以使用 RewriteCond 检查此环境变量:

RewriteCond "%{ENV:rewritten}"  =1

请注意,环境变量在外部重定向后不会保留。你可以考虑使用 [CO] 标志来设置 cookie。对于目录级和 htaccess 重写, 当最终替换作为内部重定向处理时,上一轮重写的环境变量会以 "REDIRECT_" 为前缀。

可用语言:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn