2

我设置了一个简单的 .htaccess 文件来将请求定向到示例 index.php 文件,如下所示:

RewriteEngine On

RewriteRule ^foo/(.*)$ bar/$1   # [L] here changes output

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?request=$1

访问devserver.com/foo/baz结果$_GET['request']bar/baz/baz. 将[L]标志添加到第一个RewriteRule给出了我的预期结果,即bar/baz.

我已经阅读了许多人们误解 [L] 标志的问题/答案,认为它将结束所有重写。我知道情况并非如此,并且根本看不到 [L] 标志在这里应该如何真正发挥作用。

以下是我设想在这里发生的步骤,首先没有 [L]:

  1. 请求网址开头为foo/baz
  2. 请求匹配第一条规则,被重写为bar/baz
  3. 请求继续处理并匹配RewriteCond
  4. 请求也匹配下一条规则,重写为index.php?request=bar/baz
  5. 新的迭代开始于请求index.php?request=bar/baz
  6. 新请求不匹配任何规则,是最终输出

并使用 [L]:

  1. 请求网址开头为foo/baz
  2. 请求匹配第一条规则,被重写为bar/baz
  3. 新的迭代开始于请求bar/baz
  4. 请求不匹配,直到RewriteCond
  5. 请求匹配下一条规则,被重写为index.php?request=bar/baz
  6. 新的迭代开始于请求index.php?request=bar/baz
  7. 新请求不匹配任何规则,是最终输出

在这个简化的场景中,我无法理解如何baz被复制。我有什么误解?

编辑:在第一个 RewriteRule 下方添加这个会导致最终$_GET['request']test/baz. 不知道这意味着什么:

RewriteCond %{REQUEST_URI} ^/foo/baz$
RewriteRule ^bar/baz/baz$ /test
4

1 回答 1

1

相比之下,在每条规则之前附加到URI的PATH_INFO只反映了本轮mod_rewrite处理之前的PATH_INFO的值。因此,如果 URI 的大部分被匹配并复制到多个 RewriteRule 指令中的替换中,则不考虑 URI 的哪些部分来自当前的 PATH_INFO,最终的 URI 可能会附加多个 PATH_INFO 副本。

为了防止这种情况发生,您需要使用 DPI 标志,这样您的规则将是:

RewriteEngine On

RewriteRule ^foo/(.*)$ bar/$1 [DPI]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?request=$1

DPI 标志将负责从中删除路径信息。你可以在这里阅读更多。

于 2013-07-03T08:38:22.950 回答