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

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

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

目标:当上游 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;
}

我的步骤:

  • 我已经准备好了静态错误页面/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_page使用;proxy_intercept_errors onlocationserver

它们似乎都无法说服 nginx 显示我的错误页面。为什么不行?我错过了什么?

答案1

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

location / {
    try_files   $uri $uri/ @server;
    error_page  403 = @server;
}

基本上,我试图变得聪明并捕捉$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;
}

答案2

如果不查看您的整个配置,很难确定,因为对我来说,即使没有您采取任何额外措施,这个配置也能正常工作。我首先尝试了您的所有配置,然后逐一删除一些配置,看看是否有任何变化。

没有必要使用 proxy_intercept_errors,因为当 nginx 无法连接到后端时,它自己会生成 502。我确认,设置和取消设置后,这对我有用。

我在服务器块中添加的所有内容是:

error_page 502 /error-502.html;

location = /error-502.html {
  internal;
  root /srv/www/errors;
}

在我的设置中,我的静态错误页面位于 /srv/www/errors,但其他方面没有什么不同。

您必须在服务器范围或服务器块中的其他地方进行配置,这些配置会干扰或覆盖。请注意位置的优先规则,这可能是一个因素。

相关内容