Apache HTTP 服务器版本 2.5

本文档是 mod_rewrite
参考文档的补充。它描述了关于
mod_rewrite 最重要的概念之一——
即何时应避免使用它。
mod_rewrite 应被视为最后的手段,
当其他替代方案不能满足需求时才使用。在有更简单替代方案的情况下使用它,
会导致配置混乱、脆弱且难以维护。
了解有哪些替代方案可用是掌握 mod_rewrite 的重要一步。
请注意,这些示例中的许多不会在你的特定服务器配置中直接生效, 因此理解它们非常重要,而不仅仅是将示例复制粘贴到你的配置中。
最常见的适合使用 mod_rewrite 的情况是,
最佳解决方案需要访问服务器配置文件,而你没有该访问权限。
某些配置指令只能在服务器配置文件中使用。因此,
如果你处于只能使用 .htaccess 文件的托管环境中,
你可能需要借助 mod_rewrite。
mod_alias 提供了 Redirect 和 RedirectMatch 指令,
它们提供了将一个 URL 重定向到另一个 URL 的方法。
这种简单的将一个 URL 或一类 URL 重定向到其他地方的操作,
应使用这些指令而不是
RewriteRule 来完成。
RedirectMatch 允许你在重定向条件中包含正则表达式,
提供了使用 RewriteRule 的许多好处。
RewriteRule 的一个常见用途是重定向整类 URL。
例如,/one 目录中的所有 URL 必须重定向到
http://one.example.com/,或者所有 http
请求必须重定向到 https。
这些情况更适合使用 Redirect 指令处理。
请记住,Redirect 会保留路径信息。也就是说,
对 URL /one 的重定向也会重定向其下的所有 URL,
例如 /one/two.html 和 /one/three/four.html。
要将 /one 下的 URL 重定向到
http://one.example.com,请执行以下操作:
Redirect "/one/" "http://one.example.com/"
要将一个主机名重定向到另一个,例如将
example.com 重定向到 www.example.com,
请参阅规范主机名方案。
要将 http URL 重定向到 https,
请执行以下操作:
<VirtualHost *:80>
ServerName www.example.com
Redirect "/" "https://www.example.com/"
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
# ... SSL 配置放在这里
</VirtualHost>
当同一作用域中存在其他 RewriteRule 指令时,
使用 RewriteRule 来完成此任务可能是合适的。
这是因为,当 Redirect 和 RewriteRule
指令在同一作用域中时,无论它们在配置文件中的出现顺序如何,
RewriteRule 指令都会先执行。
对于 http 到 https 的重定向,
当你无权访问主服务器配置文件,
而被迫在 .htaccess 文件中执行此任务时,
使用 RewriteRule 是合适的。
Alias
指令提供了从 URI 到目录的映射——通常是
DocumentRoot 之外的目录。
虽然可以使用 mod_rewrite 执行此映射,
但出于简便性和性能原因,Alias
是首选方法。
Alias "/cats" "/var/www/virtualhosts/felines/htdocs"
当你无权访问服务器配置文件时,使用 mod_rewrite
执行此映射可能是合适的。Alias 只能在服务器或虚拟主机上下文中使用,
不能在 .htaccess 文件中使用。
如果你的服务器启用了 Options FollowSymLinks,
符号链接将是实现同样目标的另一种方式。
虽然可以使用 mod_rewrite 处理虚拟主机,
但这很少是正确的方式。创建单独的
<VirtualHost>
块几乎总是正确的做法。如果你有大量的虚拟主机,
可以考虑使用 mod_vhost_alias 来自动创建这些主机。
mod_macro 等模块对于动态创建大量虚拟主机也很有用。
当你使用的托管服务不提供服务器配置文件的访问权限,
你只能使用 .htaccess 文件进行配置时,
使用 mod_rewrite 创建虚拟主机可能是合适的。
请参阅使用 mod_rewrite 的虚拟主机文档, 了解如何实现此目的(如果这仍然看起来是正确的方法)。
RewriteRule 提供了 [P] 标志,用于将重写后的 URI 通过
mod_proxy 传递。
RewriteRule "^/?images(.*)" "http://imageserver.local/images$1" [P]
但是,在许多情况下,当不需要实际的模式匹配时(如上面的示例所示),
ProxyPass 指令是更好的选择。
上面的示例可以表示为:
ProxyPass "/images/" "http://imageserver.local/images/"
请注意,无论你使用
RewriteRule 还是
ProxyPass,
你仍然需要使用
ProxyPassReverse
指令来捕获后端服务器发出的重定向:
ProxyPassReverse "/images/" "http://imageserver.local/images/"
当同一作用域中有其他 RewriteRule 生效时,
你可能需要使用 RewriteRule 代替,
因为 RewriteRule 通常会在 ProxyPass
之前生效,可能会抢先处理你要完成的操作。
mod_rewrite 经常用于根据特定环境变量或请求头
是否存在来执行特定操作。使用
<If>
指令可以更高效地完成此操作。
例如,考虑使用 RewriteRule
来强制使用规范主机名(如 www.example.com 而不是
example.com)的常见场景。可以使用
<If>
指令来完成,如下所示:
<If "req('Host') != 'www.example.com'">
Redirect "/" "http://www.example.com/"
</If>
此技术可用于根据任何请求头、响应头或环境变量执行操作,
在许多常见场景中替代 mod_rewrite。