proxy_intercept_errors 可拦截后端真实返回的404,但需同location内启用on、绑定error_page 404并用internal定义降级页;若后端返回200+业务404则无效。

proxy_intercept_errors 本身不能劫持后端返回的 404——它只对 proxy_pass 流量中后端主动返回的 4xx/5xx 响应生效,而 404 是典型可拦截状态码之一。但关键前提在于:这个 404 必须由上游服务真实返回,且响应体非空;若 Nginx 自身生成 404(比如请求路径没匹配到任何 location),则完全不走 proxy_intercept_errors 流程。
要让 404 被正确拦截并跳转至降级页,需满足三个硬性条件:开启拦截、绑定状态码、提供可访问的降级资源。
必须在同一 location 中启用并绑定 404
proxy_intercept_errors on; 和 error_page 404 ... 必须出现在同一个 location 块内(或其直接父级如 server),否则不生效:
location /api/ {
proxy_pass http://backend;
proxy_intercept_errors on; # 开启拦截开关
error_page 404 = @notfound; # 显式捕获 404,重定向到命名 location
}
用 internal location 安全提供降级页
不能让 /notfound.html 被用户直连访问,必须用 internal 限制:
location @notfound {
internal; # 外部无法 curl /@notfound 或直接访问
root /usr/share/nginx/html; # 文件实际在 /usr/share/nginx/html/notfound.html
try_files /notfound.html =404; # 若文件不存在,返回 404(避免循环)
}
注意后端是否真返回 404
很多场景下,后端即使资源缺失也返回 200 OK + {"code":404},这种状态码仍是 200,proxy_intercept_errors 完全无视。验证方式很简单:
curl -I http://your-nginx-domain/api/missing-item
如果响应头里是 HTTP/1.1 404 Not Found,说明后端配合;如果是 200 OK,那就得改后端逻辑,或改用 map + add_header 配合 Lua 等更重方案。
补充建议:避免和静态 404 冲突
Nginx 自身的 error_page 404(用于静态文件未找到)和 proxy_intercept_errors 的 404 是两套机制。如果你在 server 块写了全局 error_page 404 /404.html,又在 location 里配了 proxy_intercept_errors on,以 location 内的 error_page 为准——所以别在 server 层覆盖,专注在代理路径里精细化控制。
不复杂但容易忽略











