[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 服务器错误。