Nginx可通过error_page指令拦截500/502/503/504等错误并重定向至内部location,配合return返回标准化JSON响应,需配置internal、add_header及变量插值,确保作用域正确且JSON语法合法。

在 Nginx 作为 API 网关使用时,统一拦截后端服务返回的错误状态(如 500、502、503、504),并返回标准化、可读性强的 JSON 响应,是提升系统健壮性和前端体验的关键一环。这不仅避免了暴露后端细节,也便于监控和客户端统一处理。
利用 error_page 拦截指定 HTTP 状态码
Nginx 本身不主动“捕获”后端错误,而是通过 error_page 指令将特定响应状态码重定向到内部 location 进行处理。关键点在于:该指令需放在能生效的作用域(如 server 或 location 块内),且要确保 proxy_pass 后产生的错误状态能被识别。
- 在 upstream 后的 location 中配置 error_page 500 502 503 504 = /error;,注意等号表示“替换状态码”,即用 /error 返回的状态覆盖原始错误码
- 必须定义对应的内部 location(以 location = /error { ... } 开头),且该 location 需加 internal;,防止外部直接访问
- 若希望保留原始状态码(如仍返回 502),可去掉等号,写成 error_page 502 /error;,但此时需在 /error 中显式用 return 502,否则默认返回 200
返回结构化 JSON 响应体
在自定义错误 location 中,不依赖后端,直接由 Nginx 构造响应内容。推荐用 return 指令配合 application/json 类型,简洁可靠:
- 设置响应头:add_header Content-Type "application/json; charset=utf-8";
- 构造响应体:return 502 '{"code":502,"message":"Service unavailable","trace_id":"'$request_id'"}';
- 注意单引号包裹整个 JSON 字符串,内部双引号无需转义;变量如 $request_id 可直接插值,便于链路追踪
- 如需更复杂模板(如不同错误码对应不同 message),可用 map 指令预定义映射,再在 return 中引用
保留原始错误信息(可选进阶)
有时需要向运维或调试人员透传后端原始错误(如 upstream 的响应头 X-Error-Reason),Nginx 默认不传递这些字段。可通过以下方式增强可观测性:
- 在 proxy_pass 所在 location 中启用 proxy_intercept_errors on;(已默认开启,但建议显式声明)
- 用 proxy_hide_header 和 proxy_pass_header 控制哪些响应头透传给 /error location(注意:error_page 重定向后,原始响应头已不可见,此法仅适用于未触发 error_page 的场景)
- 更可靠的做法是:让后端在出错时主动写入自定义 header(如 X-Backend-Error),然后在 error_page location 中用 add_header X-Backend-Error $upstream_http_x_backend_error; 将其带出(需确认该变量存在)
验证与调试要点
配置生效前务必验证路径和逻辑是否闭环,常见陷阱包括:
- 忘记加 internal; 导致 /error 被外部请求直接命中,返回空或 404
- error_page 放在错误作用域(如 http 块下),对当前 server 不生效;应置于 server 或具体 location 内
- JSON 中含换行或未闭合引号会导致 Nginx 启动失败,建议用在线 JSON 校验工具预检
- 测试时用 curl -v 访问一个必然失败的接口(如停掉 upstream 服务),观察响应状态码、Content-Type 和 body 是否符合预期

















