找回密码
 新建账号

nginx fastcgi php 遇到名字以 .php 结尾的目录时无法正常访问的解决办法

[复制链接]
 楼主| 大郎 发表于 2026-8-16 19:59 | 显示全部楼层 |阅读模式
nginx 的 location 不能区分请求的资源是普通文件还是目录,而处理 php 脚本文件的 location 只能用文字匹配的方式来匹配——通常是使用正则表达式来匹配 php 文件,然后在 location 内使用 fastcgi_* 指令将脚本文件交给 php 处理。
  1. location ~* "[^/]\.php(/|$)" {
  2. }
复制代码
问题在于,wuxiancheng.php 这种看起来像 php 脚本文件的文件,完全有可能是一个特殊的文件——一个名叫 wuxiancheng.php 的目录。如果它是一个文件夹,而把它当成文件交给 PHP 处理,PHP 会直接报告“Access denied.”,即使这个目录内还有 index.php 或其他索引文件。这个请求的响应是 PHP 完成的,nginx 如实转发 PHP 的响应,不会调用自己的机制来响应。而实际上,我们需要的是遇到目录时,让 nginx 来处理目录,而不是交给 PHP 去处理。
方法一、利用 rewrite 实现
相关 nginx 配置如下,可以根据实际情况调整。
  1. location ^~ /@phpish_directory {
  2.     internal;
  3.     rewrite ^/@phpish_directory(.*)$ $1 break;
  4.     try_files $uri $uri/ =404;
  5. }

  6. location ~* "[^/]\.php(/|$)" {
  7.     fastcgi_split_path_info "^(.*\.php)(/.*)?$";

  8.         if (-d $document_root$fastcgi_script_name) {
  9.             rewrite ^(.*)$ /@phpish_directory$1 last;
  10.         }
  11.         if (!-f $document_root$fastcgi_script_name) {
  12.             return 404;
  13.         }
  14.    
  15.         fastcgi_connect_timeout         5;
  16.         fastcgi_intercept_errors        off;
  17.         fastcgi_index                                index.php;
  18.     fastcgi_max_temp_file_size  2047m;
  19.         fastcgi_read_timeout                 86400;
  20.         fastcgi_send_timeout                 86400;
  21.         fastcgi_pass                                   127.0.0.1:10018;
  22.    
  23.     fastcgi_param  PATH_INFO          $fastcgi_path_info;

  24.     fastcgi_param  QUERY_STRING       $query_string;
  25.     fastcgi_param  REQUEST_METHOD     $request_method;
  26.     fastcgi_param  CONTENT_TYPE       $content_type;
  27.     fastcgi_param  CONTENT_LENGTH     $content_length;

  28.     fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
  29.     fastcgi_param  SCRIPT_FILENAME          $document_root$fastcgi_script_name;
  30.     fastcgi_param  REQUEST_URI        $request_uri;
  31.     fastcgi_param  DOCUMENT_URI       $document_uri;
  32.     fastcgi_param  DOCUMENT_ROOT      $document_root;
  33.     fastcgi_param  SERVER_PROTOCOL    $server_protocol;
  34.     fastcgi_param  REQUEST_SCHEME     $scheme;
  35.     fastcgi_param  HTTPS              $https if_not_empty;

  36.     fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
  37.     fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

  38.     fastcgi_param  REMOTE_ADDR        $remote_addr;
  39.     fastcgi_param  REMOTE_PORT        $remote_port;
  40.     fastcgi_param  SERVER_ADDR        $server_addr;
  41.     fastcgi_param  SERVER_PORT        $server_port;
  42.     fastcgi_param  SERVER_NAME        $server_name;
  43. }
复制代码
方法二、利用 HTTP 418 I'm a teapot 状态码实现
  1. location @phpish_directory {
  2.     try_files $uri $uri/ =404;
  3. }

  4. location ~* "[^/]\.php(/|$)" {
  5.     error_page 418 = @phpish_directory;
  6.     fastcgi_split_path_info "^(.*\.php)(/.*)?$";

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

  23.     fastcgi_param  QUERY_STRING       $query_string;
  24.     fastcgi_param  REQUEST_METHOD     $request_method;
  25.     fastcgi_param  CONTENT_TYPE       $content_type;
  26.     fastcgi_param  CONTENT_LENGTH     $content_length;

  27.     fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
  28.     fastcgi_param  SCRIPT_FILENAME          $document_root$fastcgi_script_name;
  29.     fastcgi_param  REQUEST_URI        $request_uri;
  30.     fastcgi_param  DOCUMENT_URI       $document_uri;
  31.     fastcgi_param  DOCUMENT_ROOT      $document_root;
  32.     fastcgi_param  SERVER_PROTOCOL    $server_protocol;
  33.     fastcgi_param  REQUEST_SCHEME     $scheme;
  34.     fastcgi_param  HTTPS              $https if_not_empty;

  35.     fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
  36.     fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

  37.     fastcgi_param  REMOTE_ADDR        $remote_addr;
  38.     fastcgi_param  REMOTE_PORT        $remote_port;
  39.     fastcgi_param  SERVER_ADDR        $server_addr;
  40.     fastcgi_param  SERVER_PORT        $server_port;
  41.     fastcgi_param  SERVER_NAME        $server_name;
  42. }
复制代码
需要注意的是,这样做实际上是人为触发了 418 状态,更推荐使用方法一。
关于配置 nginx php fastcgi,可以阅读另外一篇文章:nginx fastcgi php 在文件不存在时返回自己的 404 响应而不是 PHP 的 No input file specified.

手机版|轻松e站

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

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