首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Nginx + phpFPM: PATH_INFO始终为空

Nginx + phpFPM: PATH_INFO始终为空
EN

Stack Overflow用户
提问于 2013-12-31 06:52:02
回答 8查看 17K关注 0票数 10

我在Debian上配置了nginx稳定(1.4.4) + PHP (使用FastCGI,php-fpm)。这很好用:

代码语言:javascript
复制
     location ~* ^/~(.+?)(/.*\.php)$ {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        alias /home/$1/public_html$2;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_index index.php;
        autoindex on;
     }

我使用PATH_INFO变量,因此我在fastcgi_params中添加了以下行:

代码语言:javascript
复制
fastcgi_param   PATH_INFO       $fastcgi_path_info;

和/etc/php5/fpm/php.ini中:

代码语言:javascript
复制
cgi.fix_pathinfo = 0

我认为这应该是可行的,但是当我打印出所有服务器变量时,PATH_INFO总是为空:

代码语言:javascript
复制
    array (
  'USER' => 'www-data',
  'HOME' => '/var/www',
  'FCGI_ROLE' => 'RESPONDER',
  'QUERY_STRING' => '',
  'REQUEST_METHOD' => 'GET',
  'CONTENT_TYPE' => '',
  'CONTENT_LENGTH' => '',
  'SCRIPT_FILENAME' => '/usr/share/nginx/html/srv_var.php',
  'SCRIPT_NAME' => '/srv_var.php',
  'PATH_INFO' => '',
  'REQUEST_URI' => '/srv_var.php',
  'DOCUMENT_URI' => '/srv_var.php',
  'DOCUMENT_ROOT' => '/usr/share/nginx/html',
  'SERVER_PROTOCOL' => 'HTTP/1.1',
  'GATEWAY_INTERFACE' => 'CGI/1.1',
  'SERVER_SOFTWARE' => 'nginx/1.4.4',
  .....
)

我想不出问题出在哪里。有什么想法吗?

EN

回答 8

Stack Overflow用户

发布于 2018-03-13 08:04:34

我偶然发现了一个解决方案。$fastcgi_path_info变量与$fastcgi_split_path_info协同工作,需要在location块中进行设置。以下是在我们的环境中工作的方法:

代码语言:javascript
复制
location ~ [^/]\.php(/|$) {
    root /var/www/jurism-php;
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }
    # Mitigate https://httpoxy.org/ vulnerabilities
    fastcgi_param HTTP_PROXY "";
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    include fastcgi_params;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
}

fastcgi_split_path_info下的Nginx documentation中也有一个示例。

(...我现在看到的匹配不止一个以上的帖子。(可能需要在include语句之后设置PATH_INFO行,以避免扰乱值。)

票数 6
EN

Stack Overflow用户

发布于 2018-02-17 14:26:57

我的工作配置如下:

代码语言:javascript
复制
location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+\.php)($|/.*);
    try_files $fastcgi_script_name =404;

    set $path_info $fastcgi_path_info;
    fastcgi_param PATH_INFO $path_info;

    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index  index.php;  
    include fastcgi_params;    
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_ignore_client_abort off;
}
票数 4
EN

Stack Overflow用户

发布于 2021-04-25 18:07:40

使用PHP进行调试

首先,在现代PHP中,PATH_INFO存储在$_SERVER数组中。尝试:

代码语言:javascript
复制
echo "called SCRIPT_NAME: {$_SERVER['SCRIPT_NAME']} with PATH_INFO: {$_SERVER['PATH_INFO']}";

在任何情况下,phpinfo()都会帮助你找到大量的内部php信息,比如变量和配置。

Nginx配置

至于NginX的配置,大部分已经在其他帖子中解释过了。因此,这里是一个总结,并仔细查看以下示例位置块的详细信息和原因:

代码语言:javascript
复制
location /main.php {
  # regex to split $uri to $fastcgi_script_name and $fastcgi_path_info
  fastcgi_split_path_info ^(.+?\.php)(/.*)$;

  # Check that the PHP script exists before passing it
  try_files $fastcgi_script_name =404;

  # Bypass the fact that try_files resets $fastcgi_path_info
  # see: http://trac.nginx.org/nginx/ticket/321
  set $path_info $fastcgi_path_info;
  fastcgi_param PATH_INFO $path_info;

  # set the standard fcgi paramters
  include fastcgi.conf;

  # pass the request to the socket
  fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}

逐行解释

fastcgi_split_path_info会在SCRIPT_NAMEPATH_INFO之间对你的位置进行划分。

代码语言:javascript
复制
fastcgi_split_path_info ^(.+?\.php)(/.*)$;

正则表达式的第一个括号中的表达式提取SCRIPT_NAME,而第二个提取PATH_INFO

重述正则表达式

  • 第一个正则表达式组(.+?\.php)需要任何字符(点.),至少一次或多次(加号+)。带有尾随的.php.php中的点被转义为\.php,因此从字面上看它不是“任何字符”。

问号?使加号变得懒惰(+?),因此求值在第一个.php后缀处停止。

代码语言:javascript
复制
- **E.g.** - `/some.php/next.php/path-info` is evaluated to a `SCRIPT_NAME` of `/some.php` with a `PATH_INFO` of `/next.php/path-info`; beware, not to a `SCRIPT_NAME` of `/some.php/next.php` with a `PATH_INFO` of `/path-info`.

  • 第二个正则表达式组(/.*)基本上将所有以斜杠开头的内容都作为正则表达式

  • 前导^和尾随$将表达式绑定到行首和行尾。

下一行检查提取的脚本是否确实作为文件存在:

代码语言:javascript
复制
try_files $fastcgi_script_name =404;

否则,它将返回一个404错误。这可以防止将不存在的文件提供给PHP处理器,但是有重置$fastcgi_path_info变量的坏习惯(参见:http://trac.nginx.org/nginx/ticket/321)。

一种解决方法是将$fastcgi_path_info存储在$path_info中,并将FCGI参数设置为存储的$path_info。这是通过下面两行完成的:

代码语言:javascript
复制
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;

然后在fastcgi.conf的include中设置其他FCGI参数。这个文件,有时也被命名为fastcgi_params,应该由您的发行版提供。

代码语言:javascript
复制
include fastcgi.conf;

最后将请求传递给当前的PHP实例套接字(这里是PHP 7.4):

代码语言:javascript
复制
fastcgi_pass unix:/run/php/php7.4-fpm.sock;

结论

现在请记住,只有当周围的location块命中时,所有这些才会发生。上面的示例是一个前缀位置,这意味着每个位置都是匹配的,它以前缀/main.php开头。对于只有一个名为main.php的中心文件的路由应用程序来说,这是一种典型的配置。要捕获所有.php文件,必须使用正则表达式,它可以像^.+?\.php(/|$)一样简单。.php后面的(/|$)表示位置的.php部分后面要么有反斜杠(以及更多字符),要么什么都没有。子目录也是允许的,所以表达式基本上匹配包含字符串.php的每个位置,只要它在末尾或后面跟着一个斜杠。

代码语言:javascript
复制
location ~ ^.+?\.php(/|$) {
  #...
}

由于该位置只是允许进入下一块的守卫,因此最终的PHP文件名和路径信息仍然被如上所述地拆分。如果结果文件名不存在,则返回404。

这只是一个简单的配置。当然,有很多种方法可以配置位置正则表达式,以满足特定应用程序的需要。要深入了解所有这些细节,只需一本小书。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20848899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档