Apache HTTP Server 版本 2.4

本文档是对 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 下的所有 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 configuration goes here
</VirtualHost>
如果在同一范围内还有其他 RewriteRule 指令,则使用 RewriteRule 来执行此任务可能是合适的。这是因为,当同一范围内存在 Redirect 和 RewriteRule 指令时,RewriteRule 指令将首先运行,无论它们在配置文件中的出现顺序如何。
在 http-to-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] 标志,用于通过 mod_proxy 传递重写的 URI。
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。