捕获上游 (502) 错误并显示自定义错误页面

bit*_*inn 2 nginx custom-errors

这个问题早就应该回答了,但尽管阅读了许多常见的答案,但我似乎无法弄清楚,有人可以指出为什么我的配置不起作用吗?

目标:当上游 server_api 关闭时(例如,其工作进程崩溃),我希望 nginx 显示我的自定义错误页面。

我的配置:

location @server {
    proxy_pass http://server_api;
    proxy_redirect off;
    ...

    proxy_intercept_errors on;
    error_page 502 /error-502.html;
}

error_page 502 /error-502.html;

location = /error-502.html {
    internal;
    root /srv/my-server/html;
}
Run Code Online (Sandbox Code Playgroud)

我的步骤:

  • 我已/srv/my-server/html/error-502.html准备好静态错误页面,与其他静态资产具有相同的权限和所有者。
  • 我已经停止了我的上游服务,并看到[error] 2359#0: *25 connect() failed (111: Connection refused) while connecting to upstream出现在日志中。
  • 现在我尝试让我的自定义错误页面显示 502 错误。
  • 我曾尝试error_page在两者或其中之一serverlocation块上进行设置。
  • 我试图error_pageproxy_intercept_errors onlocationserver块;

他们似乎都没有说服 nginx 显示我的错误页面。为什么不?我错过了什么?

bit*_*inn 6

感谢 Justin 和 Michael 为我指明了正确的方向,这确实是一个导致我麻烦的位置块,特别是:

location / {
    try_files   $uri $uri/ @server;
    error_page  403 = @server;
}
Run Code Online (Sandbox Code Playgroud)

基本上,我试图变得聪明并捕获$uri/错误(当您尝试访问存在但没有索引文件或自动索引的文件夹时会发生 403)并将其重定向到@server阻止。

try_files $uri $uri/ @server;孤独还不够吗?

想象一下你试图访问http://example.com/,nginx 会说,哦,这个文件夹存在(它是你的root)但没有找到索引,并抛出 403 而不是传递到@server块。

因此我的 403 解决方案,但我没有意识到它带来了代价:这意味着 nginx 已经捕获了一个错误并error_page在同location一块中使用它来处理它(通过将它传递给@server)。

将此与我在问题中的测试相结合,它表明 nginx(v1.7.x)此时将忽略进一步的error_page指令并改用默认 502。

有趣的部分:我们如何解决这个问题?

我的解决方案是设置一个完全匹配的根路由,现在不再需要在根上捕获 403,并且error_page可以按预期工作。

error_page 502 /error-502.html;

location = /error-502.html {
    internal;
    root /srv/example.com/html;
}

location = / {
    try_files $uri @server;
}

location / {
    try_files $uri $uri/ @server;
}
Run Code Online (Sandbox Code Playgroud)