[英]Nginx + phpFPM: PATH_INFO always empty
我在 Debian 上配置了 nginx stable (1.4.4) + PHP(使用 FastCGI、php-fpm)。 这工作正常:
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 中添加了以下行:
fastcgi_param PATH_INFO $fastcgi_path_info;
在 /etc/php5/fpm/php.ini 中:
cgi.fix_pathinfo = 0
我认为这应该可行,但是当我打印出所有服务器变量时,PATH_INFO 始终为空:
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',
.....
)
我想不出问题出在哪里。 有什么想法吗?
我偶然发现了一个解决方案。 $fastcgi_path_info
var 与$fastcgi_split_path_info
一起使用,需要在 location 块中设置。 以下是在我们的环境中起作用的内容:
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;
}
Nginx 文档中的fastcgi_split_path_info
下也有一个示例。
(...我现在看到匹配上面的多个帖子。可能需要在 include 语句之后设置 PATH_INFO 行,以避免破坏该值。)
我的工作配置如下:
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;
}
对于人们来到这里,阅读的东西..
问题似乎是正则表达式(regex)在
location ~* ^/~(.+?)(/.*\.php)$ {
永远不会匹配不以 .php 结尾的 uri,因此另一个正则表达式永远不会“捕获”最后一个捕获组中的任何内容。
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
因此,将第一个正则表达式更改为以下内容将“修复”该问题。
location ~ [^/]\.php(/|$) {
试试这个:
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
迟到的答案,但它可能对某人有用。
我使用了变量 REQUEST_URI 而不是 PATH_INFO。 看起来它包含与 PATH_INFO 应该具有的值相同的值。
这是我得到的。 它就像一个魅力。
https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
我遇到过这个问题,但我的情况略有不同,因为我在指令中使用了try_files
。 这是我的配置以及技术说明:
这是我的location
块的样子
location / {
include php-fpm.conf;
try_files $uri $uri/ /index.php =404;
}
和php-fpm.conf
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+?\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
set $path_info $fastcgi_path_info;
include fastcgi.conf;
fastcgi_param PATH_INFO $path_info;
这里有两个特别的通知:
brew
安装了nginx
,但它不包含PATH_INFO
参数,所以我必须手动添加它(取自此处)fastcgi_param PATH_INFO $fastcgi_path_info;
try_files
是一种特殊情况(来源)The try_files directive changes URI of a request to the one matched on the file system, and subsequent attempt to split the URI into $fastcgi_script_name and $fastcgi_path_info results in empty path info - as there is no path info in the URI after try_files.
INFO_PATH
保存到一个临时变量,然后使用该临时变量设置INFO_PATH
首先,在现代 PHP 中, PATH_INFO
存储在$_SERVER
数组中。 尝试:
echo "called SCRIPT_NAME: {$_SERVER['SCRIPT_NAME']} with PATH_INFO: {$_SERVER['PATH_INFO']}";
在任何情况下, phpinfo()
都会帮助找到很多内部 php 信息,比如变量和配置。
至于 NginX 配置,大部分已经在其他帖子中进行了解释。 所以这是一个总结,并仔细研究了以下示例位置块的细节和原因:
location /main.php {
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
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_NAME
和PATH_INFO
之间拆分您的位置。
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
第一个括号中的表达式提取SCRIPT_NAME
第二个PATH_INFO
。 所以(.+?\\.php)
需要任何字符(点.
),至少一次或多次(加号+
)。 带有尾随.php
。 .php
的点被转义为\\.php
因此从字面上看,它不是“任何字符”。
问号?
使加号变得懒惰( +?
),因此评估在第一个.php
后缀处停止。 所以/some.php/next.php/path-info
进行评估,以一个SCRIPT_NAME
的/some.php
用PATH_INFO
的/next.php/path-info
,而不是一个SCRIPT_NAME
的/some.php/next.php
与/path-info
的PATH_INFO
。
第二个表达式基本上将所有以斜杠开头的内容作为PATH_INFO
。
前导^
和尾随$
将表达式绑定到行的开头和结尾。
下一行检查提取的脚本是否确实作为文件存在:
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
。 这是由接下来的两行完成的:
# 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
应该由你的发行版提供。
include fastcgi.conf;
然后最后将请求传递给您当前的 PHP 实例套接字(此处为 PHP 7.4):
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
现在请记住,所有这一切只会发生,如果周围的位置块被击中。 上面的例子是一个前缀位置,意味着每个位置都匹配,以前缀/main.php
。 这将是路由 PHP 应用程序的典型配置,该应用程序只有一个名为main.php
中央文件。 要捕获所有.php
文件,必须使用正则表达式,这可能像^.+?\\.php(/|$)
一样简单。 .php
后面的(/|$)
表示该位置的.php
部分后面有一个反斜杠(和更多字符)或什么都没有。 也允许使用子目录,因此表达式基本上匹配包含字符串.php
每个位置,只要它位于末尾或后跟斜杠即可。
location ~ ^.+?\.php(/|$) {
#...
}
由于位置只是允许进入以下块的守卫,因此最终的 PHP 文件名和路径信息仍按上述方式拆分。 如果生成的文件名不存在,则返回 404。 这只是一个简单的配置。 当然,配置位置正则表达式有无数种可能性,以满足您特定应用程序的需求。 要深入了解所有这些细节将是一本小书。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.