导读:本期聚焦于北京网站建设创作的《Nginx中$fastcgi_path_info变量是如何传递路径信息的?配置详解与常见陷阱》,敬请观看详情。PATH_INFO是PHP等动态语言获取路径信息的重要途径,而在Nginx与FastCGI配合时,这个变量能否正确传递往往取决于$fastcgi_path_info的配置写法。本文从正则匹配拆分URL讲起,详细分析fastcgi_split_path_info指令的工作机制,说明SCRIPT_NAME、SCRIPT_FILENAME、PATH_INFO三个FastCGI参数之间的关系,并给出ThinkPHP、Laravel等框架在伪静态场景下的完整server配置示例。同时还总结了常见的404、路径穿透等问题的排查思路,帮助读者彻底理解路径信息在Nginx与PHP-FPM之间的传递链路。

Nginx在与PHP-FPM等FastCGI后端配合时,URL中脚本名之后附加的路径信息(也就是PATH_INFO)能否正确传给后端程序,完全取决于$fastcgi_path_info这个变量的取值。不少人在部署ThinkPHP这类需要PATH_INFO的框架时,会直接套用网上的配置,一旦URL格式稍有变化就出现404或者PATH_INFO为空的情况,根本原因就是没有理解这条变量背后的匹配与拆分逻辑。本文把$fastcgi_path_info的产生、传递以及常见踩坑点完整梳理一遍。

Nginx中$fastcgi_path_info变量是如何传递路径信息的?配置详解与常见陷阱

一、PATH_INFO到底是什么,为什么需要$fastcgi_path_info

先厘清概念。当一个请求URL形如/index.php/abc/def时,在FastCGI协议层面会被拆成两部分:真正的脚本文件是/index.php,而/abc/def就是PATH_INFO。PHP端可以通过$_SERVER['PATH_INFO']拿到这段值,很多MVC框架正是靠它来实现路由分发,比如ThinkPHP的index.php/module/controller/action模式。

问题在于,Nginx并不会自动帮你拆分URL。Nginx内部本身没有一个叫PATH_INFO的原生变量,它只知道请求的完整URI。要让PHP收到正确的PATH_INFO,必须在Nginx层把URI切开,把切出来的后半段赋给一个叫$fastcgi_path_info的变量,再通过fastcgi_param指令传给后端。换句话说,$fastcgi_path_info是Nginx提供的一个承载拆分结果的容器,它本身没有默认值,需要你自己通过匹配指令去填充。

如果不传这个参数会怎样?最典型的表现是框架路由失效,$_SERVER['PATH_INFO']不存在或者为空,程序拿不到模块和控制器名,最终抛出找不到路由的异常,或者直接返回404。所以理解它不是可选项,而是这类部署场景下的必经之路。

二、fastcgi_split_path_info指令的匹配与拆分原理

填充$fastcgi_path_info靠的是fastcgi_split_path_info指令。它接收一个正则表达式,要求至少包含两个捕获组,第一个捕获组对应脚本路径,第二个捕获组对应PATH_INFO部分。Nginx会用请求URI去匹配这个正则,匹配成功后,第一组捕获结果自动存入$fastcgi_script_name,第二组存入$fastcgi_path_info。

来看最经典的写法:

location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass 127.0.0.1:9000;
}

这段配置里,正则^(.+?\.php)(/.*)$是关键。以/index.php/admin/index/index为例,惰性匹配的.+?\.php会匹配到/index.php,剩余的/admin/index/index落入第二个捕获组。注意这里必须用惰性匹配,如果写成贪婪的(.+\.php),遇到/a.php/b.php这种URL时脚本名会被错误地识别成/a.php/b.php,导致文件查找失败。

location本身的写法也有讲究。[^/]\.php(/|$)表示匹配类似/xxx.php/xxx.php/yyy的请求,这个正则同时覆盖了带PATH_INFO和不带PATH_INFO两种情况。如果location写成~ \.php$,那么以.php结尾的请求能进来,但/index.php/abc这种URL根本不会进入这个location,后面的拆分自然无从谈起,这是很多人配置后仍然404的首要原因。

还有一点容易被忽视:当请求URI中没有PATH_INFO部分(比如访问的就是/index.php本身)时,正则的第二个捕获组(/.*)匹配不到任何内容,此时$fastcgi_path_info为空字符串,传给PHP的PATH_INFO也就是空值,这是正常现象,不会影响脚本执行。

三、三个FastCGI参数的配合关系与完整示例

拆分完成后,真正传递给PHP的是几个fastcgi_param,它们各司其职。SCRIPT_FILENAME告诉PHP-FPM要执行哪个文件,通常由$document_root拼接$fastcgi_script_name得到;PATH_INFO就是拆出来的路径信息;而SCRIPT_NAME在设置了split指令后等于脚本路径部分。三者的对应关系可以用下面的例子直观理解。

请求URISCRIPT_FILENAMEPATH_INFO
/index.php/var/www/html/index.php(空)
/index.php/article/read/var/www/html/index.php/article/read
/api.php/v1/user/var/www/html/api.php/v1/user

以ThinkPHP5为例,一份可以直接使用的server配置如下:

server {
    listen 80;
    server_name demo.ipipp.com;
    root /var/www/thinkphp/public;

    location / {
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.php?s=$1 last;
        }
    }

    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }
}

注意include fastcgi_params与手写param的顺序问题。如果fastcgi_params文件里本身已经有fastcgi_param SCRIPT_NAME $fastcgi_script_name之类的定义,而你在include之前又定义过同名参数,FastCGI会收到重复键值。虽然多数情况下PHP取最后一个,但建议把include放在前面,自己的显式定义放在后面,行为更可控。

四、常见问题排查与安全注意事项

第一个高频问题是PATH_INFO始终为空。排查顺序建议是:先确认请求确实进入了正确的location(可以临时把access_log格式里加上$uri和$fastcgi_path_info观察);再检查location正则是否覆盖了带路径后缀的形式;最后确认fastcgi_param PATH_INFO $fastcgi_path_info;这一行没有遗漏。三步走完基本都能定位。

第二个问题是路径穿透漏洞。历史上出现过经典的/logo.jpg/x.php攻击:由于Nginx把URI拆分后交给PHP,而PHP在查找文件时遇到不存在的路径会向前回溯,最终把图片当PHP执行,造成代码执行漏洞。修复方式一方面是升级Nginx与PHP版本,另一方面在配置层面加上try_files $fastcgi_script_name =404;,确保脚本文件真实存在才交给后端:

location ~ [^/]\.php(/|$) {
    try_files $fastcgi_script_name =404;
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
}

第三个常见坑是cgi.fix_pathini相关的PHP配置。cgi.fix_pathinfo在php.ini中默认为1,表示PHP允许对SCRIPT_PATH做回溯猜测。如果出于安全把它改成0,同时又希望依赖Nginx传递的PATH_INFO,务必保证Nginx侧的拆分正则足够精确,否则可能出现原本正常的路由突然失效的情况。两者配合调试时,可以在脚本里打印$_SERVER确认SCRIPT_FILENAME、PATH_INFO、SCRIPT_NAME的实际值,比盲猜配置高效得多。

总结一下,$fastcgi_path_info的核心链路是:location正则放行带后缀的URI,fastcgi_split_path_info负责拆分并填充变量,fastcgi_param负责把变量交给PHP。理解了这条链路,无论是部署框架、排查404还是加固安全,都能做到心中有数。

Nginx配置fastcgi_path_infoPATH_INFO修改时间:2026-09-11 09:08:45

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260911/54576.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。