Nginx状态码由请求生命周期多阶段协同生成并决定后续行为,需结合location、try_files、error_page及upstream响应设计;error_page接管响应体,proxy_intercept_errors控制上游透传,map实现动态路由。

状态码处理不是简单地返回一个数字,而是 Nginx 请求生命周期中多个阶段协同作用的结果。它既反映请求的真实结果,也决定后续行为(如重定向、错误页跳转、缓存策略),需结合 location 匹配、try_files 逻辑、error_page 指令及 upstream 响应共同设计。
理解状态码的生成源头
Nginx 自身生成的状态码通常出现在以下场景:
- 静态资源缺失:当 try_files 尝试所有路径均失败,且最后一个参数是命名 location(如 @notfound)时,若该 location 内无内容返回,Nginx 默认返回 404;
- 权限拒绝:access 模块拦截(如 deny all)、auth_basic 验证失败,触发 403;
- 客户端错误:解析请求头超限、HTTP 方法不被允许(如对只支持 GET 的 location 发送 POST),返回 400 或 405;
- 后端异常:proxy_pass 转发后,上游服务返回 5xx 或非预期 4xx,Nginx 默认透传该状态码(除非显式拦截)。
用 error_page 精准接管状态码响应
error_page 是控制状态码最终呈现的核心指令,它不改变状态码本身,而是将指定状态码的响应体替换为自定义内容或内部重定向:
- 语法格式为
error_page 404 /404.html;,表示当当前上下文(server 或 location)内产生 404 时,内部发起 URI 为/404.html的请求; - 可链式处理:
error_page 502 503 504 /gateway-error.html;; - 配合
recursive_error_pages on;可在自定义错误页中再次触发 error_page(如 /gateway-error.html 本身返回 404); - 注意作用域:server 块中的 error_page 对所有 location 生效;location 内定义的会覆盖外层同码配置。
结合 proxy_intercept_errors 控制上游状态码透传
当使用 proxy_pass 时,上游返回的错误状态码默认直接返回给客户端。启用拦截后,Nginx 才会用自身 error_page 规则响应:
- 添加
proxy_intercept_errors on;到 location 或 upstream 上下文中; - 此时 404/500 等上游响应不再透传,而是交由当前层级的 error_page 处理;
- 务必配合
proxy_buffering on;(默认开启),否则拦截可能失效; - 常见组合:
proxy_intercept_errors on; error_page 500 502 503 504 /maintenance.html;。
利用 map 指令实现动态状态码路由
map 可根据请求特征(如 User-Agent、Referer、URL 参数)动态设置变量,再结合 if 或 error_page 实现条件化响应:
- 例如区分 API 与页面请求:
map $request_uri $error_type { ~^/api/ "api"; default "web"; }; - 再在 error_page 中引用:
error_page 404 = @notfound_$error_type;; - 定义两个命名 location:
location @notfound_api { return 404 '{"error":"not found"}'; }和location @notfound_web { rewrite ^(.*)$ /404.html break; }; - 这样同一 404 状态码,API 返回 JSON,Web 返回 HTML 页面,语义更清晰。
状态码处理的关键在于分清“谁生成”和“谁响应”。Nginx 不强制修改上游状态码,但提供完整链路控制能力——从拦截、重写到渲染,每一步都可定制。实际配置中,建议优先用 error_page + proxy_intercept_errors 统一兜底,再按业务需要叠加 map 动态分支,避免过度依赖 rewrite 或 if 判断。


















