nginx 的 location 不能区分请求的资源是普通文件还是目录,而处理 php 脚本文件的 location 只能用文字匹配的方式来匹配——通常是使用正则表达式来匹配 php 文件,然后在 location 内使用 fastcgi_* 指令将脚本文件交给 php 处理。- location ~* "[^/]\.php(/|$)" {
- }
复制代码 问题在于,wuxiancheng.php 这种看起来像 php 脚本文件的文件,完全有可能是一个特殊的文件——一个名叫 wuxiancheng.php 的目录。如果它是一个文件夹,而把它当成文件交给 PHP 处理,PHP 会直接报告“Access denied.”,即使这个目录内还有 index.php 或其他索引文件。这个请求的响应是 PHP 完成的,nginx 如实转发 PHP 的响应,不会调用自己的机制来响应。而实际上,我们需要的是遇到目录时,让 nginx 来处理目录,而不是交给 PHP 去处理。
方法一、利用 rewrite 实现
相关 nginx 配置如下,可以根据实际情况调整。- location ^~ /@phpish_directory {
- internal;
- rewrite ^/@phpish_directory(.*)$ $1 break;
- try_files $uri $uri/ =404;
- }
- location ~* "[^/]\.php(/|$)" {
- fastcgi_split_path_info "^(.*\.php)(/.*)?$";
- if (-d $document_root$fastcgi_script_name) {
- rewrite ^(.*)$ /@phpish_directory$1 last;
- }
- if (!-f $document_root$fastcgi_script_name) {
- return 404;
- }
-
- fastcgi_connect_timeout 5;
- fastcgi_intercept_errors off;
- fastcgi_index index.php;
- fastcgi_max_temp_file_size 2047m;
- fastcgi_read_timeout 86400;
- fastcgi_send_timeout 86400;
- fastcgi_pass 127.0.0.1:10018;
-
- fastcgi_param PATH_INFO $fastcgi_path_info;
- fastcgi_param QUERY_STRING $query_string;
- fastcgi_param REQUEST_METHOD $request_method;
- fastcgi_param CONTENT_TYPE $content_type;
- fastcgi_param CONTENT_LENGTH $content_length;
- fastcgi_param SCRIPT_NAME $fastcgi_script_name;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- fastcgi_param REQUEST_URI $request_uri;
- fastcgi_param DOCUMENT_URI $document_uri;
- fastcgi_param DOCUMENT_ROOT $document_root;
- fastcgi_param SERVER_PROTOCOL $server_protocol;
- fastcgi_param REQUEST_SCHEME $scheme;
- fastcgi_param HTTPS $https if_not_empty;
- fastcgi_param GATEWAY_INTERFACE CGI/1.1;
- fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
- fastcgi_param REMOTE_ADDR $remote_addr;
- fastcgi_param REMOTE_PORT $remote_port;
- fastcgi_param SERVER_ADDR $server_addr;
- fastcgi_param SERVER_PORT $server_port;
- fastcgi_param SERVER_NAME $server_name;
- }
复制代码 方法二、利用 HTTP 418 I'm a teapot 状态码实现- location @phpish_directory {
- try_files $uri $uri/ =404;
- }
- location ~* "[^/]\.php(/|$)" {
- error_page 418 = @phpish_directory;
- fastcgi_split_path_info "^(.*\.php)(/.*)?$";
- if (-d $document_root$fastcgi_script_name) {
- return 418;
- }
- if (!-f $document_root$fastcgi_script_name) {
- return 404;
- }
-
- fastcgi_connect_timeout 5;
- fastcgi_intercept_errors off;
- fastcgi_index index.php;
- fastcgi_max_temp_file_size 2047m;
- fastcgi_read_timeout 86400;
- fastcgi_send_timeout 86400;
- fastcgi_pass 127.0.0.1:10018;
-
- fastcgi_param PATH_INFO $fastcgi_path_info;
- fastcgi_param QUERY_STRING $query_string;
- fastcgi_param REQUEST_METHOD $request_method;
- fastcgi_param CONTENT_TYPE $content_type;
- fastcgi_param CONTENT_LENGTH $content_length;
- fastcgi_param SCRIPT_NAME $fastcgi_script_name;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- fastcgi_param REQUEST_URI $request_uri;
- fastcgi_param DOCUMENT_URI $document_uri;
- fastcgi_param DOCUMENT_ROOT $document_root;
- fastcgi_param SERVER_PROTOCOL $server_protocol;
- fastcgi_param REQUEST_SCHEME $scheme;
- fastcgi_param HTTPS $https if_not_empty;
- fastcgi_param GATEWAY_INTERFACE CGI/1.1;
- fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
- fastcgi_param REMOTE_ADDR $remote_addr;
- fastcgi_param REMOTE_PORT $remote_port;
- fastcgi_param SERVER_ADDR $server_addr;
- fastcgi_param SERVER_PORT $server_port;
- fastcgi_param SERVER_NAME $server_name;
- }
复制代码 需要注意的是,这样做实际上是人为触发了 418 状态,更推荐使用方法一。
关于配置 nginx php fastcgi,可以阅读另外一篇文章:nginx fastcgi php 在文件不存在时返回自己的 404 响应而不是 PHP 的 No input file specified. |
|