找回密码
 新建账号

nginx fastcgi php 在文件不存在时返回自己的 404 响应而不是 PHP 的 No input file specified.

[复制链接]
 楼主| 大郎 发表于 2026-8-16 15:08 | 显示全部楼层 |阅读模式
nginx fastcgi 在文件不存在时返回自己的 404 响应而不是 PHP 的 No input file specified.,是很有必要的。因为 “No input file specified.”真正的意思是没有找到文件,也就是说文件不存在,而不是“没有指定要处理的脚本文件”。文件不存在就应该给出 404 响应,但“No input file specified.”的响应状态码是 200,这会让人困惑。要实现 nginx 接管 404 响应,有几个方法。
方法一、配置 nginx 劫持 fast CGI 程序的错误
  1. fastcgi_intercept_errors on;
复制代码
这能在 PHP 找不到脚本文件时将 404 错误交给 nginx 处理,但会导致设置状态为 4xx、5xx 等数值的脚本中的响应体被 nginx 吞掉。
方法二、在处理 PHP 的 location 配置块中使用 try_files
  1. try_files $uri $uri/ =404;
复制代码
这能在 PHP 找不到脚本文件时将 404 错误交给 nginx 处理,但会导致有 PATH INFO 的 URL 直接被判定为文件不存在。
比如访问 /index.php/wuxiancheng.cn/robots.txt 时,虽然 index.php 存在,但由于 nginx 测试的是完整的 $uri,最终的判定结果是文件 robots.txt 不存在。
方法三、先测试文件是否存在,再交给 PHP 处理。
在处理 PHP 的 location 配置块中添加
  1. if (!-f $document_root$fastcgi_script_name) {
  2.             return 404;
  3.         }
复制代码
这样配置有一个暗坑:如果受访问的资源是一个目录,nginx 也会返回 404。这种场景下,实际上应该报 403 而不是 404 或 200。因此还要加一个判断文件夹的逻辑。
  1. if (-d $document_root$fastcgi_script_name) {
  2.             return 403;
  3.         }
  4.         if (!-f $document_root$fastcgi_script_name) {
  5.             return 404;
  6.         }
复制代码
要正确处理 PATH INFO,还要分割脚本文件和 PATH INFO。综合配置如下。
  1. location ~* "[^/]\.php(/|$)" {
  2.     fastcgi_split_path_info "^(.*\.php)(/.*)?$";

  3.         if (-d $document_root$fastcgi_script_name) {
  4.             return 403;
  5.         }
  6.         if (!-f $document_root$fastcgi_script_name) {
  7.             return 404;
  8.         }
  9.    
  10.         fastcgi_connect_timeout         5;
  11.         fastcgi_intercept_errors        off;
  12.         fastcgi_index                                index.php;
  13.     fastcgi_max_temp_file_size  2047m;
  14.         fastcgi_read_timeout                 86400;
  15.         fastcgi_send_timeout                 86400;
  16.         fastcgi_pass                                   127.0.0.1:10018;
  17.    
  18.     fastcgi_param  PATH_INFO          $fastcgi_path_info;

  19.     fastcgi_param  QUERY_STRING       $query_string;
  20.     fastcgi_param  REQUEST_METHOD     $request_method;
  21.     fastcgi_param  CONTENT_TYPE       $content_type;
  22.     fastcgi_param  CONTENT_LENGTH     $content_length;

  23.     fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
  24.     fastcgi_param  SCRIPT_FILENAME          $document_root$fastcgi_script_name;
  25.     fastcgi_param  REQUEST_URI        $request_uri;
  26.     fastcgi_param  DOCUMENT_URI       $document_uri;
  27.     fastcgi_param  DOCUMENT_ROOT      $document_root;
  28.     fastcgi_param  SERVER_PROTOCOL    $server_protocol;
  29.     fastcgi_param  REQUEST_SCHEME     $scheme;
  30.     fastcgi_param  HTTPS              $https if_not_empty;

  31.     fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
  32.     fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

  33.     fastcgi_param  REMOTE_ADDR        $remote_addr;
  34.     fastcgi_param  REMOTE_PORT        $remote_port;
  35.     fastcgi_param  SERVER_ADDR        $server_addr;
  36.     fastcgi_param  SERVER_PORT        $server_port;
  37.     fastcgi_param  SERVER_NAME        $server_name;
  38. }
复制代码
这样配置,实际上仍然存在问题:当一个文件夹叫 wuxiancheng.php,看名字它是 php 脚本文件,而实际上它是目录时,它会被意外当成 php 文件处理而无法作为目录处理。这个问题的解决办法见另外一篇文章:nginx fastcgi php 遇到名字以 .php 结尾的目录时无法正常访问的解决办法

手机版|轻松e站

GMT+8, 2026-8-24 09:38

快速回复 返回顶部 返回列表