Nginx反向代理:仅拦截自身特定错误的实现方法
如何让Nginx仅处理反向代理自身产生的50x错误
这个需求太常见了——很多时候我们只想处理Nginx代理层自己搞出来的50x错误(比如连不上后端、超时),而上游服务器返回的50x(比如后端代码崩了返回的500)我们想直接透传给用户。下面给你两个实用的方案,都是基于Nginx内置变量来区分错误来源的:
方案一:针对特定代理层错误码直接拦截
大部分情况下,Nginx代理自身产生的50x错误集中在502(网关错误,无法连接后端)和504(网关超时,后端响应太慢),而上游服务器返回的50x多是500、503这类。我们可以直接针对这两个码做自定义处理,其他50x透传:
server { listen 80; server_name your-domain.com; location / { proxy_pass http://your-backend-server; proxy_intercept_errors on; # 必须开启,否则Nginx不会拦截错误 # 只处理Nginx代理层的502/504错误,跳转到自定义处理location error_page 502 504 = @proxy_errors; # 上游返回的500/503直接透传原状态码和内容 error_page 500 503 = $status; } # 自定义代理错误处理逻辑 location @proxy_errors { # 示例1:返回自定义HTML页面 return 502 "<!DOCTYPE html> <html> <head><title>Proxy Error</title></head> <body><h1>抱歉,后端服务暂时无法连接</h1></body> </html>"; # 示例2:重定向到静态错误页面 # rewrite ^ /static/proxy-error.html break; # root /path/to/your/static/files; } }
这个方案简单直接,适合大多数场景——如果你确认上游不会返回502/504,或者即使返回也不需要拦截,用这个就够了。
方案二:用$upstream_status变量精准区分错误来源
如果需要更严格的区分(比如上游也可能返回502/504,你只想拦截Nginx自己产生的),可以利用$upstream_status变量:
- 当错误来自上游服务器时,
$upstream_status会被设置为上游返回的状态码(比如500、502); - 当错误是Nginx代理自身产生的(比如无法连接后端、超时),
$upstream_status是空值。
配置示例:
server { listen 80; server_name your-domain.com; location / { proxy_pass http://your-backend-server; proxy_intercept_errors on; # 把所有50x错误都转到统一处理location error_page 500 502 503 504 = @handle_all_errors; } location @handle_all_errors { # 仅当$upstream_status为空时(代理层错误),执行自定义处理 if ($upstream_status = "") { return 502 "<h1>代理层错误:无法连接或访问后端超时</h1>"; } # 否则透传上游的错误状态码和原始内容 return $status $upstream_http_content_type $upstream_response_body; } }
这个方案可以精准区分错误来源,不管状态码是什么,只要是Nginx自己搞出来的错误就处理,上游的错误原样返回。
几个关键注意事项
- 一定要开启
proxy_intercept_errors on,否则Nginx会直接把所有上游错误透传,不会触发任何error_page规则; - 测试时可以故意把后端地址改成无效IP(触发502),或者设置极短的
proxy_connect_timeout(触发504),验证自定义处理是否生效; - 如果需要更细致的判断,还可以结合
$upstream_response_time变量——上游返回的错误会有响应时间,而代理层错误的这个变量是空值,逻辑和$upstream_status类似。
内容的提问来源于stack exchange,提问作者Rockietto
相关产品推荐
相关产品推荐

