【问题标题】:Strange behaviour from REQUEST_FILENAME?来自 REQUEST_FILENAME 的奇怪行为?
【发布时间】:2013-12-15 23:38:47
【问题描述】:

我正在使用 MAMP,基于虚拟主机的设置创建了一个 '.dev' tld 用于工作。 我网站的 .htaccess 像这样使用 mod_rewrite:

RewriteEngine on
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}\.php -f

RewriteRule ^(.*)$ $1.php [L]
RewriteRule ^(butchers|news|recipes)/([a-zA-Z0-9-/]+)$ /$1.php?s=$2 [L,QSA]

我的网站提供肉店目录。列表视图由butchers.php 显示,可通过butchers 访问。详细视图由butchers.php?s=some-butcher-name 显示,可通过butchers/some-butcher-name 访问。 如您所见,相同的机制适用于新闻和食谱部分。

好的,事情是这样的:这曾经工作过。它工作得很好,然后我在升级 MAMP 后重新启动了我的系统,现在它给了我一个内部服务器错误。我假设我已经从 Apache 1.x 升级到 2.x;升级后我不得不重做我的虚拟主机配置,但其他一切都是香草(与上次相同)除了我禁用了MultiViews。 mod_rewrite 日志如下所示(前几列被截断)

[perdir /Users/myusername/Sites/dev/sitename/] add path info postfix: /Users/myusername/Sites/dev/sitename/butchers -> /Users/myusername/Sites/dev/sitename/butchers/example-butcher
[perdir /Users/myusername/Sites/dev/sitename/] strip per-dir prefix: /Users/myusername/Sites/dev/sitename/butchers/example-butcher -> butchers/example-butcher
[perdir /Users/myusername/Sites/dev/sitename/] applying pattern '^(.*)$' to uri 'butchers/example-butcher'
[perdir /Users/myusername/Sites/dev/sitename/] RewriteCond: input='/Users/myusername/Sites/dev/sitename/butchers' pattern='!-d' => matched
[perdir /Users/myusername/Sites/dev/sitename/] RewriteCond: input='/Users/myusername/Sites/dev/sitename/butchers' pattern='!-f' => matched
[perdir /Users/myusername/Sites/dev/sitename/] RewriteCond: input='/Users/myusername/Sites/dev/sitename/butchers.php' pattern='-f' => matched
[perdir /Users/myusername/Sites/dev/sitename/] rewrite 'butchers/example-butcher' -> 'butchers/example-butcher.php'
[perdir /Users/myusername/Sites/dev/sitename/] add per-dir prefix: butchers/example-butcher.php -> /Users/myusername/Sites/dev/sitename/butchers/example-butcher.php
[perdir /Users/myusername/Sites/dev/sitename/] trying to replace prefix /Users/myusername/Sites/dev/sitename/ with /
strip matching prefix: /Users/myusername/Sites/dev/sitename/butchers/example-butcher.php -> butchers/example-butcher.php
add subst prefix: butchers/example-butcher.php -> /butchers/example-butcher.php
[perdir /Users/myusername/Sites/dev/sitename/] internal redirect with /butchers/example-butcher.php [INTERNAL REDIRECT]

这是我对正在发生的事情的理解:

  • 我的 UA 要求 butchers/example-butcher
  • 在 RewriteCond 中使用 REQUEST_FILENAME 时,它输出的路径只有butchers,而不是butchers/example-butcher
  • 这通过了,因为butchers.php 是真实的
  • 根据 RewriteRule,允许重写附加“.php”
  • 当它追加时,它会将它追加到 original 请求中,butchers/example-butcher
  • 内部重定向使用butchers/example-butcher.php 重新启动循环

然后进程再次以同样的问题开始 - RewriteCond 测试这个奇怪的、不完整的路径版本,但在正确的路径上运行。这种情况发生了十次,在 apache 达到限制并发出 500 之前积累了越来越多的.php

  • 请求butchers/example-butcher
  • butchers.php 是真实文件吗?是的!
  • 追加.php
  • 请求butchers/example-butcher.php
  • butchers.php 是真实文件吗?是的!
  • 追加.php
  • 请求butchers/example-butcher.php.php
  • ...等等

所以,我可以看到 为什么 存在一个循环,以及为什么它要不断将.php 添加到自身,我只是不明白为什么 REQUEST_FILENAME 只给出了第一级小路。我找不到任何说明这是规定行为的文档。

有什么想法吗?我已经为此花费了一整天的时间:/

谢谢!

【问题讨论】:

    标签: php apache .htaccess mod-rewrite


    【解决方案1】:

    这是因为%{REQUEST_FILENAME} 变量不仅仅是映射到单个文件/目录的请求URI。当您有以下要求时:

    /foo/bar/something
    

    你有两个文件:

    /foo.php
    /foo/bar.php
    /foo/bar/something.php
    

    条件:

    RewriteCond %{REQUEST_FILENAME}.php -f
    

    将是真的,因为 mod_rewrite 还考虑了 PATH_INFO。如果您有这些 php 文件之一,那么 mod_rewrite 将尝试变得聪明并确定请求的 URI 是否实际上在请求的 URI 路径中,并将 .php 添加到 that 路径节点而不是 at最后。要严格检查请求+.php是否存在,你需要这样做:

    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
    

    【讨论】:

      猜你喜欢
      • 2020-02-10
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多