很久没更新了,最近部署thinkphp项目的时候遇到一个问题,初步定位是nginx的规则导致的
先说现象,在项目界面点了用户登出按钮后,跳转到了这个url: http://ip/index.php/
然后出现的是如下图所示
于是去排查nginx的配置文件,判断是这个location的问题
location ~ \.php/ {
if ($request_uri ~ ^(.+\.php)(/.+?)($|\?)) { }
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_NAME $1;
fastcgi_param PATH_INFO $2;
fastcgi_param SCRIPT_FILENAME $document_root$1;
}
先上最后修改结果,也就修改了SCRIPT_FILENAME
location ~ \.php/ {
if ($request_uri ~ ^(.+\.php)(/.+?)($|\?)) { }
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_NAME $1;
fastcgi_param PATH_INFO $2;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
修改之后reload了nginx,再次访问http://ip/index.php/就正常了
排查过程
因为笔者不是特别清楚这些参数的含义,所以换了下思路,去查看了nginx的error.log,找到了下面的关键字:
于是笔者到搜索引擎查了下“see security.limit_extensions”,看到了这位大佬的博客
https://blog.csdn.net/lovelycolor/article/details/96584232
博客中提到需要检查fastcgi_param的SCRIPT_FILENAME,于是笔者去研究了下nginx中的各种参数含义
首先搞清楚,参数SCRIPT_FILENAME到底指的是什么?
https://www.cnblogs.com/qk2014/p/8855783.html
这位大佬的博客写得很清楚,SCRIPT_FILENAME是当前执行程序的绝对路径及文件名
nginx是通过"root /path/to/dir/;“指定了url的在系统中的相对路径(这么说可能不严谨),
举个例子,假如url是http://ip:port/abc/def/,那么执行程序就应该从系统的”/path/to/dir/abc/def/"路径下寻找
而变量 d o c u m e n t r o o t 的 内 容 就 是 / p a t h / t o / d i r / , 根 据 S C R I P T F I L E N A M E 的 定 义 , 自 然 不 能 只 等 于 document_root的内容就是/path/to/dir/,根据SCRIPT_FILENAME的定义,自然不能只等于 documentroot的内容就是/path/to/dir/,根据SCRIPTFILENAME的定义,自然不能只等于document_root,还需要再指定到具体的文件
原来的nginx配置中写的是fastcgi_param SCRIPT_FILENAME $document_root$1,笔者并没有搞清楚在这次请求中$1应该是什么(index.php/ ??),还望知道的大佬可以指教
那么fastcgi_script_name指的是什么?笔者查了nginx的文档,如下:
$fastcgi_script_name
request URI or, if a URI ends with a slash, request URI with an index file name configured by the fastcgi_index directive appended to it. This variable can be used to set the SCRIPT_FILENAME and PATH_TRANSLATED parameters that determine the script name in PHP. For example, for the “/info/” request with the following directives
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
the SCRIPT_FILENAME parameter will be equal to “/home/www/scripts/php/info/index.php”.
When using the fastcgi_split_path_info directive, the $fastcgi_script_name variable equals the value of the first capture set by the directive.
照顾一下英语一般般的同学,fastcgi_script_name指的是请求uri,或者当uri以"/"为结尾,那么fastcgi_script_name=uri/$fastcgi_index
eg
nginx配置:
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
当请求uri = /info/时,SCRIPT_FILENAME = /home/www/scripts/php/info/index.php
在本次场景的请求中,SCRIPT_FILENAME = $document_root/index.php,其中$fastcgi_index=index.php
通过上述的nginx错误日志,原来的配置中的请求url是/index.php/,修改配置后请求url变成了/index.php,正常请求到了对应的文件
下面链接是笔者看到的$fastcgi_script_name的用法,里面的解答挺不错的
https://serverfault.com/questions/465607/nginx-document-rootfastcgi-script-name-vs-request-filename