如何在nginx中设置回退错误页面?

我正在configurationnginx处理一些错误页面和其他“默认”媒体文件(如favicon.ico和robots.txt),我遇到了一个小问题,让我的工作方式,我想要的某些错误页面。

基本上,我想要做的是服务某些服务器的根目录下的服务器的文件,例如/var/www/someserver.com/robots.txt。 如果该文件不存在,我想让nginx进入“default”,即/var/www/default/robots.txt。 这是我如何(成功)configuration的基本要点:

server { ... root /var/www/someserver.com; location ~* ^/(robots\.txt)$ { error_page 404 = @default; } location @default { root /var/www/default; } } 

这很好。

我试图做错误页面的相同,我不能做到这一点,虽然:

 server { ... root /var/www/someserver.com; error_page 404 /404.html; location ~* ^/(404\.html)$ { error_page 404 = @default; } location @default { root /var/www/default; } } 

请注意,这个“有效”的意思是,如果你访问某个server.com/404.html,它将首先加载/var/www/someserver.com/404.html,然后回落到/ var / www / default /404.html如果没有find。 但是,如果您访问某个server.com/blahblah,则只会在/var/www/someserver.com/中设置404页面。 如果该文件不存在,它不会回退到默认目录。

无论如何,你可能可能是我试图完成的(这就是为什么我包括第一个工作的例子)。

有任何想法吗?

编辑:

根据Martin F的回答,这就是我最终的结果:

 # Doesn't work when error page is returned on a POST request server { ... root /var/www/someserver.com; error_page 404 = @notfound; error_page 500 502 504 = @server_error; error_page 503 = @maintenance; location @notfound { try_files /404.html /../default/404.html =404; } location @server_error { try_files /500.html /../default/500.html =500; } location @maintenance { try_files /503.html /../default/503.html =503; } } 

这工作真棒。 上面的error_pages和位置的实际块在每个虚拟主机都包含的server_defaults.conf文件中,这就是为什么我没有将path硬编码到每个位置并使用相对path作为默认值的原因。

编辑2:

这种方法有一个问题。 如果您将POST发送到返回错误的URL,则POST请求方法将与try_files尝试一起发送。 这(对我来说)会导致一个405不允许的错误,因为nginx本质上是试图POST到例如/default/500.html,而不是只是获取该页面。

编辑3:

我发布了一个解决scheme,这个解决scheme非常接近我原来的想法。

我最终以更接近我原来的想法。 我失踪的关键是结果recursive_error_pages 。 我真正要做的就是把这个“打开”,我原来的想法工作。 以下是我的conf的相关部分现在的样子:

 server { ... root /var/www/someserver.com/; error_page 400 404 /404.html; error_page 500 502 504 /500.html; error_page 503 /503.html; recursive_error_pages on; location ~* ^/(404\.html|500\.html|503\.html)$ { log_not_found off; error_page 404 = @default; } location @default { log_not_found on; root /var/www/default; } } 

我还包括了其他的错误types,这些错误types并不是我原来的问题的一部分,因为这最终导致了Martin F的方法的困难。 log_not_found指令只是确保在原始根目录中找不到错误页面时,我的日志中没有log_not_found

try_files是去这里的路。 以下configuration应该可以工作,但是我没有testing过它的语法错误。

 server { ... root /var/www; location / { try_files /someserver.com$uri /default$uri /someserver.com$uri/ /default$uri/ @notfound; } location @notfound { try_files /someserver/404.html /default/404.html =404; # =404 should make it use the nginx-default 404 page. } } 

不幸的是,我的答案迟了几年,但我认为这可能有助于未来的search者。 我安装的Nginx版本是1.2.4,我创build了以下configuration代码片段,

 server { server_name www.example.com root /var/www/example ## Errors -> Locations error_page 400 /400.html; error_page 403 /403.html; error_page 404 /404.html; error_page 500 502 503 504 /50x.html; ## Locations -> Fallback location = /400.html { try_files /400.html @error; internal; } location = /403.html { try_files /403.html @error; internal; } location = /404.html { try_files /404.html @error; internal; } location = /50x.html { try_files /50x.html @error; internal; } ## Fallback Directory location @error { root /var/www/error; } } 

我发现包含“proxy_intercept_errors on”是至关重要的。 在包含error_page的任何位置块中。

如果没有这个设置,那么位置块将拦截从上游返回的错误代码。

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors