8

我了解[L]以下重写规则意味着它是“最后一个”,但我不清楚范围是什么

例如,当有多个 .htaccess 文件时,其中一些带有[L],哪些将适用?

例子:

root.com/subdirectory1/subdirectory2

  ^           ^            ^      
  |           |            |
  A           B            C

如果每个目录中都有一个 .htaccess 文件...

  1. 他们将按什么顺序申请?
  2. 如果它们相互矛盾,哪个优先?
  3. 他们是否连续申请?第一个的结果是否传递给下一个?
  4. 是否会应用较早(或相同)文件中的匹配结果,该文件来自较晚的规则?
  5. 如果[L]在较早的文件中有一个,是否会考虑其他文件?
4

1 回答 1

15

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

于 2013-04-08T00:33:41.957 回答