proxy_intercept_errors 是拦截开关,需与同作用域的 error_page 配合使用,将502/503/504等错误映射为自定义静态页(如/offline.html),并确保文件存在、路径正确、权限可读;常见失效原因包括响应体非标准状态码、作用域不匹配、路径或权限错误。

proxy_intercept_errors 本身不生成页面,也不美化错误——它只是一个“拦截开关”。真正把后端返回的 502、503、504 等负载错误变成用户可见的友好页面,靠的是它和 error_page 的配合:前者允许 Nginx 暂停透传,后者决定展示什么内容。
必须成对出现:开启拦截 + 明确映射状态码
只写 proxy_intercept_errors on; 是无效的。它必须和 error_page 在同一作用域(比如同一个 location 或其父级 server 块)中同时存在:
- 在代理块中启用:
proxy_intercept_errors on; - 紧接着声明要接管哪些状态码:
error_page 502 503 504 /offline.html; - 确保
/offline.html文件真实存在,且路径可被 Nginx 访问(例如放在root /usr/share/nginx/html;对应的目录下)
让降级页真正“友好”:静态文件 + 安全服务
你配置的 HTML 文件就是最终呈现给用户的全部界面。要让它可靠又可控:
- 把
offline.html放在 Nginx 能直接读取的目录里,比如/usr/share/nginx/html/offline.html - 为这个 URI 单独定义一个内部 location,明确指定 root 并加
internal;防止用户绕过业务直接访问:location = /offline.html {<br> internal;<br> root /usr/share/nginx/html;<br> } - HTML 内容建议轻量:内联 CSS 实现基础响应式,避免依赖外部 JS 或 CDN 图片;文字提示如“服务暂时繁忙,请稍后再试”比“503 Service Unavailable”更友好
常见失效原因:不是配错了,而是没对上
明明写了配置,却还是看到原始的 502 页面?大概率是以下情况之一:
- 后端实际返回的是
200 OK+ JSON 错误体(例如{"code":503,"msg":"timeout"}),而 proxy_intercept_errors 只识别 HTTP 状态码,不解析响应体 -
error_page写在server块,但proxy_intercept_errors on;写在子location里,且该 location 没继承到 error_page(作用域不匹配) - 静态页路径写错,或 Nginx 没有读取权限,导致 fallback 失败后又触发默认 500 错误(此时需要额外配
error_page 500,形成嵌套) - 对静态资源请求(如
/logo.png)也开了proxy_intercept_errors,这类 404 更适合用try_files处理,避免丢失 Content-Type
进阶:按错误类型分页,提升体验一致性
不同错误背后含义不同,用户感知也应有区分:
- 502(上游连接失败)→ 展示“系统连接异常,请检查网络”
- 504(上游超时)→ 展示“请求处理较慢,请稍候重试”
- 503(上游主动拒绝)→ 展示“服务维护中,预计 XX 时间恢复”
- 可通过多条
error_page分别指定:error_page 502 /502.html; error_page 504 /504.html; - 也可用
map指令结合$upstream_status动态选页,实现统一入口、差异化响应











