如何配置Nginx将所有404请求路由到PHP脚本并允许PHP自定义响应状态码
如何配置Nginx将所有404请求路由到PHP脚本并允许PHP自定义响应状态码
兄弟,我懂你现在的困扰——想让所有404请求都跳转到PHP脚本处理,还得让PHP能自己说了算响应状态码,对吧?先看看你现在的Nginx配置,咱们一步步把问题解决掉。
你的初始Nginx配置是这样的:
server { listen 81; listen [::]:81; root /srv/http/paste.lan/www; autoindex on; client_max_body_size 20M; index index.txt index.html index.htm index.php; server_name paste.lan; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } # pass PHP scripts to FastCGI server location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; } # deny access to .htaccess files location ~ /\.ht { deny all; } }
你之前试了三种方法,都有各自的问题:
- Attempt #1:把
location /里的try_files改成$uri $uri/ /index.php,结果只有非.php结尾的404请求能转到index.php,像/DoesNotExist.php这种还是会返回Nginx默认404。这是因为Nginx会优先匹配.php的location块,直接检查文件是否存在,不存在就直接返回404了,根本没走到你的跳转逻辑。 - Attempt #2:加了
error_page 404 /index.php,虽然所有404都能转到PHP,但不管你在PHP里用http_response_code()设置什么状态码,客户端收到的都是404——这是因为Nginx强制把响应状态码固定成了触发跳转的404。 - Attempt #3:改成
error_page 404 =200 /index.php,结果又走向另一个极端,所有响应都是200,PHP里设置的400之类的状态码完全不起作用,等于Nginx又把状态码给硬改了。
正确的解决方案
核心思路是:让Nginx把404请求转发给PHP,同时不强制覆盖PHP返回的状态码。只需修改两处配置即可:
修改后的完整Nginx配置:
server { listen 81; listen [::]:81; root /srv/http/paste.lan/www; autoindex on; client_max_body_size 20M; index index.txt index.html index.htm index.php; server_name paste.lan; location / { try_files $uri $uri/ =404; } # 关键修改:用=符号但不指定状态码,让PHP自己决定响应状态 error_page 404 = /index.php; # pass PHP scripts to FastCGI server location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; # 如果你的snippets/fastcgi-php.conf里没设置下面这行,记得加上,确保PHP能找到脚本文件 # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location ~ /\.ht { deny all; } }
原理说明
error_page 404 = /index.php;是关键:这里的等号后面没有指定状态码,意味着Nginx会完全使用后端(PHP-FPM)返回的状态码,不再强制用404覆盖。- 原来的
.phplocation块已经正确配置了FastCGI,能把PHP脚本的响应内容和状态码原封不动地返回给客户端。 - 不管是普通路径的404,还是
.php结尾的不存在请求,都会触发404规则跳转到index.php,而且PHP里设置的任何状态码都会生效——比如你在PHP里写http_response_code(400),客户端就会收到400;写http_response_code(200),就会收到200。
这样就完美解决了你之前遇到的所有问题啦!
备注:内容来源于stack exchange,提问作者hanshenrik
相关产品推荐
相关产品推荐

