Nginx中try_files配置及404重定向对.php后缀失效问题排查
Hey, let's break down why your 404 redirect isn't working for PHP paths and fix it step by step:
The Core Issues
- PHP 404s aren't being intercepted properly: Even though you added
fastcgi_intercept_errors on;in your PHP location blocks, we need to make sure Nginx actually catches those 404s from FastCGI and triggers yourerror_pagerule. - Non-PHP paths aren't throwing 404s: Your current
try_files $uri $uri/ /index.php?$args;in the root location forwards missing paths toindex.php, which returns a 200 homepage instead of a 404—so the redirect never fires. - Rewrite rule edge cases: The original regex works for most paths, but we can make it more robust to cover PHP suffixes and root-level 404s.
Fixes to Your Nginx Config
1. Ensure Global 404 Interception
Keep error_page 404 = @notfound; near the top of your server block (before most locations) so all routes inherit this rule. Double-check that every PHP-handling location has fastcgi_intercept_errors on; (you already have this, but it's critical for catching PHP-generated 404s).
2. Adjust Root Location to Trigger 404s
Modify the location / block's try_files to return a 404 instead of forwarding to index.php when paths don't exist:
location / { location ~* \.(jpg|jpeg|gif|bmp|ico|png|css|js|swf|woff)$ { expires 7d; access_log off; } index index.php index.html index.htm; # Return 404 for missing non-static paths instead of serving index.php try_files $uri $uri/ =404; fastcgi_intercept_errors on; }
Note: If your site relies on index.php for routing (like a CMS or SPA), you'll need to adjust this—maybe only apply this logic to non-PHP paths, or ensure your PHP app returns proper 404s for invalid routes instead of serving the homepage.
3. Optimize the @notfound Rewrite Rule
Update the redirect logic to handle PHP suffixes and root-level 404s cleanly:
location @notfound { # Redirect paths with a subdirectory (e.g., /air/xxx.php → /air/) if ($uri ~ ^/([\w-]+)/) { rewrite ^/([\w-]+)/.*$ https://$server_name/$1/ permanent; } # Redirect root-level 404s (e.g., /missing.php → /) rewrite ^/.+$ https://$server_name/ permanent; }
This first checks for paths with a subdirectory and redirects to that parent folder, then catches any root-level missing paths and sends them to the homepage.
4. Verify PHP Block Configuration
Make sure your PHP locations retain fastcgi_intercept_errors on;—this tells Nginx to take over error handling from FastCGI, so 404s from PHP scripts trigger your redirect:
location ~ \.php$ { fastcgi_intercept_errors on; # Keep this line fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php-fpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_script_name; include /etc/nginx/fastcgi_params; }
Test the Fixes
Use curl -I to validate both scenarios:
- For PHP paths:
curl -I https://portal-dev.foo.com.br/air/uknwfileerror.phpshould return a 301 withLocation: https://portal-dev.foo.com.br/air/ - For non-PHP paths:
curl -I https://portal-dev.foo.com.br/air/uknwfileerrorshould also return a 301 to the same parent directory
内容的提问来源于stack exchange,提问作者Vinicius Peres

