Nginx拦截上游5xx需proxy_intercept_errors on与error_page成对配置于同一location中,配合internal限制的alias静态页,并确保后端响应体非空。

要让 Nginx 捕获并重构上游安全后端返回的 5xx 状态码(如 500、502、503、504),关键不是只写 proxy_intercept_errors on,而是构建一个“拦截—接管—安全返回”的闭环配置。它本身不生成内容,只决定是否把控制权交给 error_page。
必须在同一 location 中成对启用拦截与错误页绑定
单独开启 proxy_intercept_errors on 不会生效。必须在代理请求的 location 块中紧随其后声明要接管的状态码:
proxy_intercept_errors on;-
error_page 500 502 503 504 /5xx.html;(或按需细分,如error_page 502 /timeout.html;) - 确保该 location 同时包含
proxy_pass,且error_page的路径是 URI,不是文件系统路径
确保降级页可安全访问且防直接调用
用户不应能绕过代理直接请求 /5xx.html。推荐使用 internal 限制访问,并明确映射静态资源位置:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
location = /5xx.html { internal; alias /usr/share/nginx/html/5xx.html; }- 用
alias而非root可避免路径拼接错误;internal阻止外部直接访问 - 页面建议内联 CSS/JS,不依赖外部资源,防止二次请求失败
让后端响应真正可被拦截
Nginx 默认只拦截响应体长度 ≥ 512 字节的 5xx 响应。若安全后端返回精简错误(如纯文本 502 Bad Gateway 或空 body),可能跳过拦截:
- 要求后端至少返回一个字节的响应体(例如
{"status":"error"}或<p>Service unavailable</p>) - 调试时用
curl -i http://your-api/fail查看真实Content-Length和响应体 - 避免后端设置
Content-Length: 0或未发送 chunked body
避免循环和状态码混淆
常见误配会导致 5xx 接管失效或无限重定向:
- 不要在
error_page中指向同一 location(如error_page 502 /;),否则可能触发循环 - 若需保留原始状态码(如仍返回 502),写法为:
error_page 502 = /5xx.html; - 若需改为 200(统一成功响应),写法为:
error_page 502 =200 /5xx.html; - 所有配置优先放在
location块内,避免http或server级别的error_page覆盖代理逻辑

















