nginx配置pathinfo支持,最佳方案 - chunyu

时间:2021-08-22 14:03:32

〇. 前言

pathinfo有两个,1 pathinfo()函数,2 $_SERVER['PATH_INFO']。
pathinfo()是php的库函数,原生支持不需要nginx配置,$_SERVER['PATH_INFO']才需要nginx的特殊配置。
为什么要配置pathinfo,因为ThinkPHP/CodeIgniter/Yii等MVC框架都需要$_SERVER['PATH_INFO']。

一. 配置pathinfo支持之前,先让nginx支持PHP

nginx配置pathinfo支持,最佳方案 - chunyu

这里有个缺陷,就是得到的SCRIPT_NAME不准确。

二. 开始配置 pathinfo

nginx配置pathinfo支持,最佳方案 - chunyu

这是传统的nginx - pathinfo 解决方案

三. 寻找最佳方案的途中

nginx配置pathinfo支持,最佳方案 - chunyu

因为配置文件里面PATH_INFO 跟 SCRIPT_NAME 都是使用了 $fastcgi_script_name,所以strace追踪nginx进程发现两者一样是正常的。可是从浏览器请求的效果看到PATH_INFO跟SCRIPT_NAME却不一样,虽然从最终结果看,它符合我们的要求,可是不合理呀。
我猜想,是php-fpm或者说fastcgi对此做了一些容错处理。

四. 最佳方案

nginx配置pathinfo支持,最佳方案 - chunyu

五. rewrite 隐藏index.php

nginx配置pathinfo支持,最佳方案 - chunyu

另外,现在nginx官方推荐使用try_files取代rewrite,不过try_files好像不支持正则,有兴趣的童鞋自行研究哈。给出一个例子,如下

nginx配置pathinfo支持,最佳方案 - chunyu

六. 附件

1) 上面用到的配置文件的合集

 server {
listen ;
server_name test;
charset utf-; index index.html index.htm index.php;
root /var/www/test; # rewrite 隐藏index.php
location / {
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php/$ last;
break;
}
} # 传统方案
#location ~ \.php {
# set $real_script_name $path_info;
#
# if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
# set $real_script_name $;
# set $path_info $;
# }
#
# include fastcgi_params;
# fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
# fastcgi_param PATH_INFO $path_info;
# fastcgi_param SCRIPT_NAME $real_script_name;
#
# fastcgi_pass 127.0.0.1:;
#} # 寻找最佳方案的途中
#location ~ \.php {
# include fastcgi.conf;
# fastcgi_param PATH_INFO $fastcgi_script_name;
#
# fastcgi_pass 127.0.0.1:;
#} # 最佳方案
location ~ \.php {
fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi.conf;
fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_pass 127.0.0.1:;
} }

2) fastcgi.conf 的中文注释

 fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name; #脚本文件请求的路径
fastcgi_param QUERY_STRING $query_string; #请求的参数;如?app=
fastcgi_param REQUEST_METHOD $request_method; #请求的动作(GET,POST)
fastcgi_param CONTENT_TYPE $content_type; #请求头中的Content-Type字段
fastcgi_param CONTENT_LENGTH $content_length; #请求头中的Content-length字段。 fastcgi_param SCRIPT_NAME $fastcgi_script_name; #脚本名称
fastcgi_param REQUEST_URI $request_uri; #请求的地址
fastcgi_param DOCUMENT_URI $document_uri; #与$uri相同。
fastcgi_param DOCUMENT_ROOT $document_root; #网站的根目录。在server配置中root指令中指定的值
fastcgi_param SERVER_PROTOCOL $server_protocol; #请求使用的协议,通常是HTTP/.0或HTTP/1.1。 fastcgi_param GATEWAY_INTERFACE CGI/1.1; #cgi 版本
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; #nginx 版本号,可修改、隐藏 fastcgi_param REMOTE_ADDR $remote_addr; #客户端IP
fastcgi_param REMOTE_PORT $remote_port; #客户端端口
fastcgi_param SERVER_ADDR $server_addr; #服务器IP地址
fastcgi_param SERVER_PORT $server_port; #服务器端口
fastcgi_param SERVER_NAME $server_name; #服务器名,域名在server配置中指定的server_name # PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS ; 在php可打印出上面的服务环境变量
如:echo $_SERVER['REMOTE_ADDR']

3) nginx 的uri、request_uri 区别

$request_uri: /stat.php/qw/cv?id=1585378&web_id=1585378
$uri /stat.php/qw/cv
$document_uri: /stat.php/qw/cv

3) 检验 REQUEST_URI / DOCUMENT_URI / PHP_SELF / PATH_INFO

echo 'REQUEST_URI - '.$_SERVER['REQUEST_URI'];
echo '<br />DOCUMENT_URI - '.$_SERVER['DOCUMENT_URI'];
echo '<br />SCRIPT_NAME - '.$_SERVER['SCRIPT_NAME'];
echo '<br />PHP_SELF - '.$_SERVER['PHP_SELF'];
echo '<br />PATH_INFO - '.$_SERVER['PATH_INFO'];

同时strace 追踪nginx进程