该[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]
这并不一定意味着“在此处停止重写”,因为重写引擎将循环直到进入引擎的 URI 停止更改。just 意味着在[L]
重写引擎循环的当前迭代中停止重写。
关于循环内容的更多细节:
在 URL 处理管道期间,apache 尝试将 URL 映射到文件或资源。许多不同的模块在处理管道中发挥作用,例如 mod_rewrite 或 mod_proxy 或 mod_alias。在任何时候,此 URI 都可以更改、被标记为重定向、被标记为被代理、被标记为抛出错误等。当 URI 到达 mod_rewrite 时,重写引擎从 vhost 配置中收集一堆规则并适当的 htaccess 文件;注意,这里有 2 个不同的范围。每个规则范围都应用于 URI,如果没有规则匹配,则 mod_rewrite 完成。如果其中一个规则匹配,则存在内部重定向,这意味着 URI 已更改,然后重定向回处理管道和 mod_rewrite。因此,相同范围的规则再次被应用,如果其中一个规则匹配并被应用,同样的事情再次发生在规则循环中。您可以在 vhost/server 配置中设置一个指令,该指令设置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
,到您第五次得到/a-b-c-d-foo
。它将再次循环,但由于^(.*)_(.*)$
模式不匹配,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 服务器错误。