多个 .htaccess 文件中多个 mod_rewrite 规则的优先级是啥? [关闭]
Posted
技术标签:
【中文标题】多个 .htaccess 文件中多个 mod_rewrite 规则的优先级是啥? [关闭]【英文标题】:What is the precedence of multiple mod_rewrite rules in multiple .htaccess files? [closed]多个 .htaccess 文件中多个 mod_rewrite 规则的优先级是什么? [关闭] 【发布时间】:2013-03-29 22:59:10 【问题描述】:我了解[L]
遵循重写规则意味着它是“最后一个”,但我不清楚范围是什么
例如,当有多个.htaccess文件时,有的带有[L]
,哪些会适用?
例子:
root.com/subdirectory1/subdirectory2
^ ^ ^
| | |
A B C
如果每个目录下都有.htaccess文件...
-
它们将按什么顺序应用?
如果它们相互矛盾,哪个优先?
它们是否连续应用?第一次的结果会传递给下一次吗?
是否会应用较早(或相同)文件中的匹配结果,该文件来自较晚的规则?
如果早期文件中有
[L]
,是否会考虑其他文件?
【问题讨论】:
@casperOne:这是一个编程问题,恕我直言。 htacess 文件,更具体地说是 OP 询问的重写规则,会影响 Web 应用程序中的控制流。 “执行优先级”听起来确实像是程序员的问题,不是吗? 【参考方案1】:[L]
标志确实意味着“最后一个”,但它只适用于当前范围内的规则。根据您的问题,它仅适用于 htaccess 文件中的规则。如果子目录中有规则,则父目录中的任何规则都将被抛出窗口。它们根本不应用,除非您使用 RewriteOptions Inherit
指令(它会将父 htaccess 文件中的任何规则附加到规则的末尾)。
举个例子:
root.com/subdirectory1/subdirectory2
^ ^ ^
| | |
A B C
如果A、B、C中都有htaccess文件,并且全部3个都重写规则,如果有一个请求http://root.com
(你的“root.com”目录),只有A中的规则被应用。如果有人请求http://root.com/subdirectory1
,则只应用 B 中的规则,而忽略 A 中的任何规则(没有 Inherit
选项)。同样,如果有人转到http://root.com/subdirectory1/subdirectory2
,那么如果没有继承选项,则只会应用 C 中的规则。
[L]
标志在其中没有任何作用,因为这里的范围仅在 htaccess 文件的规则内。另请注意,[L]
并不一定意味着“停止重写 HERE”,因为重写引擎将循环直到进入引擎的 URI 停止更改。 [L]
只是意味着在重写引擎循环的当前迭代中停止重写。
关于循环的更多细节:
在 URL 处理管道期间,apache 尝试将 URL 映射到文件或资源。许多不同的模块在处理管道中发挥作用,例如 mod_rewrite 或 mod_proxy 或 mod_alias。在任何时候,此 URI 都可以更改、被标记为重定向、被标记为被代理、被标记为抛出错误等。当 URI 到达 mod_rewrite 时,重写引擎从 vhost 配置中收集一堆规则并适当的 htaccess 文件;请注意,这里有 2 个不同的范围。每个规则范围都应用于 URI,如果没有规则匹配,则 mod_rewrite 完成。如果其中一个规则匹配,则存在 内部重定向,这意味着 URI 已更改,然后重定向回处理管道和 mod_rewrite。因此,相同范围的规则再次被应用,如果其中一个规则匹配并被应用,同样的事情再次发生在规则循环中。您可以在名为LimitInternalRecursion
的虚拟主机/服务器配置中设置一个指令,该指令设置这些内部重定向的限制。如果重写引擎循环(即重定向回自身)的次数超过此限制(我认为默认为 10),那么您会收到 500 Internal Server 错误。
这可能听起来有点奇怪,但有很多例子想要这样做。示例:从 URI 中删除所有 _
并替换为 -
:
RewriteRule ^(.*)_(.*)$ /$1-$2 [L]
如果 URI 是 /a_b_c_d_foo
,那么第一次,URI 将更改为 /a_b_c_d-foo
,然后循环并更改为 `/a_b_c-d-foo
,然后再次更改为 /a_b-c-d-foo
,到第五次您将获得 @987654339 @。它将再次循环,但由于^(.*)_(.*)$
模式不匹配,URI 通过重写引擎并停止循环。
当人们创建不考虑循环的规则时就会出现问题,例如:将/<anything>
重写为/foo/<anything>
:
RewriteRule ^(.*)$ /foo/$1 [L]
如果 URI 是 /bar
,那么 URI 第一次被重写为 /foo/bar
,这就是想要的结果。但是 URI 在内部被重定向回重写引擎,并且再次匹配相同的规则,导致:/foo/foo/bar
,然后是:/foo/foo/foo/bar
,然后是:/foo/foo/foo/foo/bar
,直到达到内部递归限制并得到500 服务器错误。
【讨论】:
+1 写得很好。 这很棒。您能否澄清答案中的最后一句话?我从您的回答中学到了很多东西,但我不明白重写引擎“循环”的方式。 @Emerson 查看附加说明 啊哈!在最后一个有问题的示例中, [L] 无济于事,因为它只会阻止该特定循环中的进一步重写,而不是未来循环的发生。我明白了吗? @JonLin 再问一个问题:在循环过程中,如果遇到外部重写,是否会立即中断循环?例如,如果A
中的.htaccess 有RewriteRule ^(.*)$ http://www.google.com [R=301,L]
之类的东西,那么所有较低的.htaccess 都会变得无关紧要吗?以上是关于多个 .htaccess 文件中多个 mod_rewrite 规则的优先级是啥? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
一个 .htaccess 文件中有多个 RewriteBase?
一个 .htaccess 文件中有多个 RewriteBase?