On this page
使用 mod_rewrite 的高级技术
本文档是对mod_rewrite reference documentation的补充。它使用 mod_rewrite 提供了一些高级技术。
Warning
请注意,这些示例中的许多示例在您的特定服务器配置中都不会起作用,因此,理解它们,而不只是将示例剪切并粘贴到您的配置中,这一点很重要。
基于 URL 的分片
Description:
- 分配服务器负载或存储空间负担的常用技术称为“分片”。使用此方法时,前端服务器将使用 url 一致地“分片”用户或对象以分离后端服务器。
Solution:
- 在外部 Map 文件中维护了从用户到目标服务器的 Map。他们看着像是:
user1 physical_host_of_user1 user2 physical_host_of_user2 : :
我们将其放入map.users-to-hosts
文件。目的是绘制 Map。
/u/user1/anypath
to
http://physical_host_of_user1/u/user/anypath
因此,每个 URL 路径不必在每个后端物理主机上都有效。以下规则集借助 Map 文件为我们完成此操作,假设 server0 是默认服务器,如果用户在 Map 中没有任何条目,将使用该默认服务器:
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文档。
On-the-fly Content-Regeneration
Description:
- 我们希望动态生成内容,但是一旦生成内容就将其静态存储。此规则将检查静态文件是否存在,如果不存在,请生成该文件。如果需要,可以定期删除静态文件(例如,通过 cron),并将按需重新生成。
Solution:
这是通过以下规则集完成的:
# 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
,该程序会生成所请求的资源并将其保存到文档目录中,以便下次请求该资源时,可以提供静态副本。
这样,可以以静态形式提供不经常更新的文档。如果需要刷新文档,可以将它们从文档目录中删除,然后在下次请求时重新生成它们。
Load Balancing
Description:
- 我们希望使用 mod_rewrite 在多个服务器之间随机分配负载。
Solution:
- 我们将使用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
如果您希望一台特定的服务器获得比其他服务器更多的负载,请将其添加到列表中的次数更多。
Discussion
- Apache 带有一个负载均衡模块mod_proxy_balancer,它比使用 mod_rewrite 可以拼凑的任何东西都更加灵活和功能强大。
Structured Userdirs
Description:
- 一些拥有数千用户的站点使用结构化的 homedir 布局,即每个 homedir 位于子目录中(例如,以用户名的第一个字符开头)。因此,
/~larry/anypath
是/home/l/larry/public_html/anypath
,而/~waldo/anypath
是/home/w/waldo/public_html/anypath
。
- 一些拥有数千用户的站点使用结构化的 homedir 布局,即每个 homedir 位于子目录中(例如,以用户名的第一个字符开头)。因此,
Solution:
- 我们使用以下规则集将波浪号 URL 扩展为上述布局。
RewriteEngine on
RewriteRule "^/~(([a-z])[a-z0-9]+)(.*)" "/home/$2/$1/public_html$3"
Redirecting Anchors
Description:
- 默认情况下,重定向到 HTML 锚不起作用,因为 mod_rewrite 会转义
#
字符,从而将其变成%23
。反过来,这破坏了重定向。
- 默认情况下,重定向到 HTML 锚不起作用,因为 mod_rewrite 会转义
Solution:
- 使用
RewriteRule
上的[NE]
标志。 NE 代表不逃脱。
- 使用
Discussion:
- 当然,该技术还可以与默认情况下使用 mod_rewrite URL 编码的其他特殊字符一起使用。
Time-Dependent Rewriting
Description:
- 我们希望使用 mod_rewrite 根据一天中的时间提供不同的内容。
Solution:
- 有很多名为
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
的内容。
Warning
mod_cache,中间代理和浏览器可能各自缓存响应,并使任一页面显示在配置的时间窗口之外。 mod_expires可用于控制此效果。当然,您只需要动态地提供内容并根据一天中的时间对其进行自定义,就会更好。
根据 URL 部分设置环境变量
Description:
- 有时,我们希望在执行重写时保持某种状态。例如,您要记下已完成重写,以便稍后可以查看是否通过该重写发出了请求。一种方法是设置环境变量。
Solution:
- 使用[E]标志设置环境变量。
RewriteEngine on
RewriteRule "^/horse/(.*)" "/pony/$1" [E=rewritten:1]
稍后在规则集中,您可以使用 RewriteCond 检查此环境变量:
RewriteCond "%{ENV:rewritten}" "=1"
请注意,环境变量无法在外部重定向中幸免。您可以考虑使用[CO]标志来设置 Cookie。对于按目录重写和 htaccess 重写,其中最终替换被作为内部重定向处理,来自上一轮重写的环境变量以“ REDIRECT_”为前缀。