来自REQUEST_FILENAME的奇怪行为?

时间:2013-12-15 23:38:48

标签: php apache .htaccess mod-rewrite

我正在使用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 MultiViews显示。 正如您所见,相同的机制适用于新闻和食谱部分。

好的,这就是:这曾经工作。它工作正常,然后我升级MAMP后重新启动系统一段时间,现在它给了我一个内部服务器错误。我假设我已经从Apache 1.x转到2.x;升级后我不得不重做我的vhost配置,但其他一切都是vanilla(与上次相同)除了我已禁用[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] 。 mod_rewrite日志看起来像这样(前几列被截断)

butchers/example-butcher

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

  • 我的UA要求butchers
  • 在RewriteCond中使用REQUEST_FILENAME时,它会输出仅butchers/example-butcher而不是butchers.php
  • 的路径
  • 这传递,因为butchers/example-butcher是真实的
  • 根据RewriteRule
  • ,允许重写'.php'
  • 附加后,会将其附加到原始请求butchers/example-butcher.php
  • 内部重定向使用.php
  • 重新启动循环

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

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

所以,我可以看到为什么有一个循环,以及为什么要继续向自己添加{{1}},我只是不明白为什么REQUEST_FILENAME只给出了第一个级别的路径。我找不到任何说明这是规定行为的文件。

有什么想法吗?我已经烧掉了整整一个工作日:/

谢谢!

1 个答案:

答案 0 :(得分:0)

原因是%{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添加到那个路径节点在最后。要严格检查请求+ .php是否存在,您需要执行以下操作:

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