本文档描述了关于mod_rewrite
的最重要的概念之一 - 即何时避免使用它。
当发现其他替代方案缺乏时,mod_rewrite
应被视为最后的手段。当有更简单的替代方案时使用它会导致配置混乱,易碎且难以维护。了解其他替代方案是朝着mod_rewrite
掌握迈出的非常重要的一步。
注意,这些示例中的许多示例在您的特定服务器配置中不会保持不变,因此您必须了解它们,而不是仅仅将示例剪切并粘贴到您的配置中。
mod_rewrite
是正确工具的最常见情况是,当最佳解决方案需要访问服务器配置文件时,如果没有该访问权限。某些配置指令仅在服务器配置文件中可用。因此,如果您处于托管情况,只能使用.htaccess
文件,一些配置可能需要求助于mod_rewrite
。
下面我们来看看,在哪些情况下不要使用URL得写。
简单的重定向
mod_alias
提供Redirect
和RedirectMatch
指令,它们提供了将一个URL重定向到另一个URL的方法。这种简单的方式将一个URL或一类URL重定向到其他地方,应该使用这些指令而不是RewriteRule
来完成。RedirectMatch
用于在重定向标准中包含正则表达式,从而提供使用RewriteRule
的许多好处。
RewriteRule
的一个常见用途是重定向整个URL类。例如,/one
目录中的所有URL都必须重定向到http://one.example.com/
,或者所有http请求都必须重定向到https。
Redirect
指令可以更好地处理这些情况。请记住,重定向会保留路径信息。也就是说,URL /one
的重定向也会重定向其下的所有网址,例如/one/two.html
和/one/three/four.html
。
要将/one
下的网址重定向到http://one.example.com
,请执行以下操作:
Redirect "/one/" "http://one.example.com/"
要将一个主机名重定向到另一个主机名,例如example.com
重定向www.example.com
,请参阅Canonical Hostnames配置。
要将http网址重定向到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
重定向的情况下,如果您无权访问主服务器配置文件,则必须使用RewriteRule
,并且必须在.htaccess
文件中执行此任务。
URL别名
Alias指令提供从URI到目录的映射 - 通常是DocumentRoot
之外的目录。尽管可以使用mod_rewrite
执行此映射,但出于简单性和性能的原因,Alias是首选方法。
示例:
Alias "/cats" "/var/www/virtualhosts/felines/htdocs"
当您无权访问服务器配置文件时,可能需要使用mod_rewrite
执行此映射。别名只能在服务器或虚拟主机上下文中使用,而不能在.htaccess
文件中使用。
如果在服务器上启用了Options FollowSymLinks
,那么符号链接将是实现相同目标的另一种方式。
虚拟主机
尽管可以使用mod_rewrite
处理虚拟主机,但它很少是正确的方法。创建单独的<VirtualHost>
块几乎总是正确的方法。如果拥有大量虚拟主机,请考虑使用mod_vhost_alias
自动创建这些主机。
mod_macro
之类的模块对于动态创建大量虚拟主机也很有用。
如果您使用的托管服务无法访问服务器配置文件,则使用mod_rewrite
创建虚拟主机可能是合适的,因此只能使用.htaccess
文件进行配置。
有关如何实现此目的的更多详细信息,请参阅具有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/"
当在同一范围内有其他RewriteRules
生效时,可能需要使用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
。