为什么 FastCGI 不能正确处理 PATH_INFO 重写?

为什么 FastCGI 不能正确处理 PATH_INFO 重写?

我当前的主机使用 FastCGI 进行 PHP 设置,当 mod_rewrite 指令重定向到包含 PATH_INFO 部分的 URL 时,这显然会导致一些问题。例如,使用以下内容时会出现问题:

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php/$1

当使用上述方法时,导航到重写的 URL 会导致 PHP 出现“未指定输入文件。”错误消息,这意味着 PHP 没有适当地传递要解析的文件。

我从网上搜索得知,这个问题只有在 PHP 在 FastCGI 下运行时才会出现,但我还没能找到直接的答案为什么。相反,网络上显然充斥着这样的人,他们盲目地将重写改为使用查询字符串(例如,将index.php/$1上面的部分更改为index.php?/$1- 注意?),而没有真正理解潜在的问题。

我知道该问题是作为重写过程的一部分或结果而发生的,并且这不是 FastCGI 安装无法处理 PATH_INFO URL 的问题,因为$_SERVER['PATH_INFO']当我直接导航www.example.com/index.php/foobar而不经过重写过程时,该变量会被正确填充。

有人可以解释一下重写和随后移交给 PHP 期间发生了什么,导致了失败吗?

答案1

我在 PHP 文档中发现了关于此问题的两条不同信息。

第一个是 php.ini 页面中关于 cgi.fix_pathinfo 选项的内容。

cgi.fix_pathinfo 布尔值

为 CGI 提供真正的 PATH_INFO/PATH_TRANSLATED 支持。PHP 以前的行为是将 PATH_TRANSLATED 设置为 SCRIPT_FILENAME,而不去理解 PATH_INFO 是什么。有关 PATH_INFO 的更多信息,请参阅 CGI 规范。将其设置为 1 将导致 PHP CGI 修复其路径以符合规范。设置为零将导致 PHP 的行为与以前一样。默认情况下,它是打开的。您应该修复脚本以使用 SCRIPT_FILENAME 而不是 PATH_TRANSLATED。 http://php.net/manual/en/ini.core.php

第二个是在服务器变量页面。它与之前的信息相关。

'路径翻译'

在服务器完成任何虚拟到现实的映射之后,基于文件系统(而不是文档根目录)的当前脚本路径。

注意:从 PHP 4.3.2 开始,PATH_TRANSLATED 不再在 Apache 2 SAPI 下隐式设置,这与 Apache 1 中的情况不同,在 Apache 1 中,当 PATH_TRANSLATED 未被 Apache 填充时,PATH_TRANSLATED 被设置为与 SCRIPT_FILENAME 服务器变量相同的值。进行此更改是为了符合 CGI 规范,即只有在定义了 PATH_INFO 时,PATH_TRANSLATED 才应存在。Apache 2 用户可以在 httpd.conf 中使用 AcceptPathInfo = On 来定义 PATH_INFO。 http://php.net/manual/en/reserved.variables.server.php

您可以尝试在 apache conf 中禁用 MultiViews。这也可能会导致这种情况。

相关内容