【问题标题】:Why does this mod_rewrite rewrite rule cause a loop?为什么这个 mod_rewrite 重写规则会导致循环?
【发布时间】:2019-07-23 01:38:08
【问题描述】:

注意:我在 Stack Overflow 上发现了很多类似的问题,但没有一个能真正帮助我找出问题所在。导致此循环的原因可能有数百个。


我在example.com 上有一个名为user.php 的文件。我在 .htaccess 中编写了一个简单的重写规则,它从 URL 中删除了 .php 文件扩展名。

一切正常,除了在浏览器中打开 example.com/user/<anything-here> 时收到 500 错误。我实际上预计会出现 404 错误。

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+?)/?$ $1.php

我在日志中也得到以下错误:

[...] Request exceeded the limit of 10 internal redirects due to probable
      configuration error. Use 'LimitInternalRecursion' to increase the limit
      if necessary. Use 'LogLevel debug' to get a backtrace.

[...] r->uri = /user/foobar.php.php.php.php.php.php.php.php.php.php
[...] redirected from r->uri = /user/foobar.php.php.php.php.php.php.php.php.php
[...] redirected from r->uri = /user/foobar.php.php.php.php.php.php.php.php
[...] redirected from r->uri = /user/foobar.php.php.php.php.php.php.php
[...] redirected from r->uri = /user/foobar.php.php.php.php.php.php
[...] redirected from r->uri = /user/foobar.php.php.php.php.php
[...] redirected from r->uri = /user/foobar.php.php.php.php
[...] redirected from r->uri = /user/foobar.php.php.php
[...] redirected from r->uri = /user/foobar.php.php
[...] redirected from r->uri = /user/foobar.php
[...] redirected from r->uri = /user/foobar

我尝试逐步重现问题,但没有成功:

  • 条件:
    • /user/foobar → 不是目录吗? → 没错,名为foobar 的目录不存在,所以foobar 不是目录
    • /user/foobar.php → 是文件吗? → 错误,名为foobar.php 的文件不存在,所以foobar.php 不是文件
  • 重写:
    • 不重写,因为第二个条件为假; URL 保持不变 (/user/foobar)。服务器应返回 404 错误。但是,我收到了 500 错误。

究竟出了什么问题,是什么导致了循环,为什么?

【问题讨论】:

  • @LawrenceCherone 这不是问题。路径/user/foobar 不包含.php,所以这不是原因。 (如果我错了,请纠正我。)

标签: apache .htaccess mod-rewrite url-rewriting


【解决方案1】:

您可能在服务器配置中打开了MultiViews。这可能会导致 %{REQUEST_FILENAME}.php 与现有文件 user.php 匹配并使您的条件为真。

使用顶部的这一行将其关闭:

Options -MultiViews

选项MultiViews(参见http://httpd.apache.org/docs/2.4/content-negotiation.html)由运行before mod_rewrite 的Apache's content negotiation module 使用,并使Apache 服务器匹配文件的扩展名。因此,如果 /file 是 URL,那么 Apache 将提供 /file.html。

还建议你用这个替换你的规则:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ $1.php [L]

【讨论】:

  • 我在.htaccess 文件的顶部包含了Options -MultiViews,但我仍然收到同样的错误。我也硬重新加载了几次页面并清除了我的缓存。
  • 使用[L] 标志的建议新规则检查我编辑的答案。
  • 解决了这个问题。为什么在第二个重写规则中将%{REQUEST_FILENAME} 替换为%{DOCUMENT_ROOT} 并添加[L] 标志?能给我解释一下吗?
  • 正如我所写,%{REQUEST_FILENAME}.php 正在解析为 user.php 而不是 /user/foobar.php,我相信您可以删除 [L] 标志以进行测试,它仍然可以工作。
  • documentation 表示 %{REQUEST_FILENAME}.php 返回文件的完整本地文件系统路径,而不仅仅是文件名和扩展名。
猜你喜欢
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 2013-06-25
  • 2019-09-16
  • 1970-01-01
  • 2013-04-30
  • 2012-09-27
  • 1970-01-01
相关资源
最近更新 更多