我知道这已被问过一千次,但我发现的所有答案根本不起作用(对我来说或通常是那些问题的原始OP)......所以,我&# 39;尽量尽可能地解释问题,希望我们可以让它为我和之前提出过要求的其他人工作。
我的Nginx配置(删除了许多其他不相关的东西)如下:
http {
# Config from here removed
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
# Custom error pages
root /var/www/viovet_frontend;
error_page 404 = /error404.php;
# Any simple .php page
location ~ \.php$ {
root /var/www/xxxxxx;
#index index.php index.html;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Lots more config and re-write rules here removed
}
upstream phpfastcgiservers {
server xxxxx1:9001;
server xxxxx2:9001;
server xxxxx3:9001;
fair;
}
}
我尝试做的就是让Nginx捕获所有404并通过location ~ \.php$
将它们发送回PHP-FPM,以便向用户显示自定义错误页面,但我总是得到标准Nginx错误页面。
以下网址都应显示mydomain.co.uk/error404.php
的输出:
但他们实际上展示了标准的Nginx 404页面。如果location ~ \.php$
将不同的错误代码返回到404(例如5xx),那么我们就不想参与其中,只需返回FastCGI首先返回的内容和标题。
我希望这是有道理的,有人可以提供帮助。提前谢谢。
编辑:我在recursive_error_pages on;
之后尝试将# Custom error pages
添加到该行,但这实际上会导致所有Nginx 404 Not Found
错误成为Nginx 500 Internal Server Error
错误。
编辑:添加其他文件: 的 /etc/nginx/fastcgi.conf
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
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 REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
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;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_params
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 REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
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;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
我想我可能也不需要这两个! ; - )
答案 0 :(得分:14)
我终于完成了大部分工作。感谢大家提供的建议并花时间写答案。
问题是我们的error404.php
还返回了我们的错误页面,其中包含404 Not Found标头(使用header('HTTP/1.0 404 Not Found');
),然后Nginx在recursive_error_pages
关闭时拦截此错误(默认并且它显示了它自己的404页面。关闭fastcgi_intercept_errors
是解决方案。如果我们从错误文件中删除了header('HTTP/1.0 404 Not Found');
,那么我们就会收到错误,但是200
显然不是我们想要的。
然而,这并没有解决访问以.php
结尾的缺失页面的问题(因此它与位置块匹配,因为我们现在将标准PHP-FPM响应恢复为404标题的那些身体File not found.
。我可以使用Nate's answer解决这个问题,但我不需要在那里指定所有文件名。我会为此寻找另一个解决方案当我得到它时,把它贴在这里。
编辑:更完整的解决方案:
您需要拦截主要php位置区块中的错误(fastcgi_intercept_errors
为on
),然后为您的错误页面设置另一个阻止它们的区块。请参阅此配置示例:
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
# Custom error pages
recursive_error_pages off;
error_page 404 = /http_errors/404.php;
# error_page 500 501 502 503 504 = /error5xx.php; # Not sure about this yet!
# Any simple .php page
location ~ \.php$ {
root /var/www/xxxxx;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Handling error pages
location ^~ /http_errors/ {
internal;
root /var/www/xxxxx;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors off;
}
}
这意味着返回HTTP状态代码为404的任何PHP页面都会忽略自己的内容(如果有),而是会使用/http_errors/404.php
文件的内容。
答案 1 :(得分:2)
我相信你所要求的是单独的nginx是不可能的 - 除非你手动配置每个已知的.php文件。如果您可以列出已知的.php文件,则可以根据此信息检测到预期的404。而不是使用正则表达式捕获所有.php文件,而是指定已知的php文件:
将location ~ \.php$ {}
替换为:
location~ ^ /(index | foo | bar | admin / index).php $ {}
但是,如果对 index.php 这样的知名php文件的请求返回404,即使你告诉nginx它,这也不会捕获你的机器外php-fpm生成的404应该存在。
一个完整的解决方案可能需要在你的nginx服务器前面有一个额外的服务器来检测来自php-fpm / nginx的404响应,然后它会向你的后端代理另一个往返请求 error404.php 文件。您仍然遇到 error404.php 文件的问题,同时返回404本身。我查看了Varnish以查看检测到的404是否可以针对错误页面向源服务器生成第二个请求,但遗憾的是vcl_backend_error只能提供404或重试请求。清漆 - 或类似的东西 - 可能有一些方法可以实现你想要的东西,但这并不容易。
我只能说这是大多数人不在不同机器上设置nginx和php-fpm的原因之一 - 这会引起这样的麻烦。如果可能的话,你应该考虑将nginx和php-fpm保存在同一台机器上并负载平衡这些服务器。无论你认为从分离它们中得到什么好处,都可能不值得额外的问题。
答案 2 :(得分:0)
location ~ \.php$
块需要try_files来检查文件是否存在。如果不存在,则返回404,您的error404.php将接受它。
http {
# Config from here removed
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
root /var/www/xxxxxx;
# Custom error pages
error_page 404 = /error404.php;
# Any simple .php page
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Lots more config and re-write rules here removed
}
upstream phpfastcgiservers {
server xxxxx1:9001;
server xxxxx2:9001;
server xxxxx3:9001;
fair;
}
}
答案 3 :(得分:0)
你的&#34; root / var / www / xxxxxx;&#34;应该在&#34;位置<。>外面〜.php $&#34;阻止和之前&#34; error_page 404 = /error404.php;&#34;
如果您仍然无法从error404.php获取所需的404页面,我建议您使用nginx.conf的标准副本开始调试,然后从那里自定义您的error_page,因为我们的建议有效。我为自己的服务器使用了相同的配置。
如果它仍然不起作用,它应该是一个上游问题。
您还想查看
包括/etc/nginx/fastcgi.conf; 包括fastcgi_params;
查看是否有任何恶意变量。那里可能有一些重复的变量。
调试的一般经验法则。减少变量。从简单的配置开始,逐步完成自定义。
答案 4 :(得分:0)
正确的方法
error_page 404 /path/to/404.php;
我知道它有效,因为我最近构建了一个应用程序,这是错误处理的设置。请注意我使用url重写从每个目录的请求中删除index.php
。通过这种方式,您可以设置错误脚本以将信息记录到数据库中,这对于难以调试ajax错误很有用,其中包括:
error_page 500 /error/?t=500;
error_page 501 /error/?t=501;
error_page 502 /error/?t=502;
error_page 503 /error/?t=503;
error_page 400 /error/?t=400;
error_page 401 /error/?t=401;
error_page 403 /error/?t=403;
error_page 404 /error/?t=404;
error_page 405 /error/?t=405;
error_page 406 /error/?t=406;
error_page 413 /error/?t=413;
error_page 414 /error/?t=414;
error_page 418 /error/?t=418; # i'm a teapot