recursive_error_pages仅控制error_page内部错误的递归处理层级,不限制HTTP重定向;开启后最多支持10层嵌套错误处理,超限则返回500并记录循环警告。

recursive_error_pages 不处理 HTTP 重定向死循环,它只控制 error_page 内部错误的嵌套处理层级。很多人误以为开启这个指令就能“支持多次 302 跳转”或“解决重定向循环”,其实完全混淆了机制——HTTP 重定向(如 301/302)由客户端执行,而 recursive_error_pages 是服务端内部错误响应链的递归控制,两者不交叉、不联动。
它管什么:error_page 触发后的内部错误再处理
当某个 error_page 指向的 location 执行时又出错(比如返回 404、500,或被 rewrite 触发新错误),nginx 会尝试再次查找匹配的 error_page 来接管——这就是“递归错误处理”。开启 recursive_error_pages on 后,最多允许 10 层嵌套;超过即终止,返回 500 并记录:rewrite or internal redirection cycle。
- 第 1 层:主请求返回 404 → 触发
error_page 404 /fallback.html - 第 2 层:/fallback.html location 中又返回 404 → 再次触发
error_page 404 /backup.html - 第 3 层:/backup.html location 中仍失败 → 继续向下找……直到第 10 层
- 第 11 层:直接 500 + 日志告警,不再继续
它不管什么:HTTP 重定向(3xx)和 return/rewrite 跳转
以下行为完全不受 recursive_error_pages 影响:
-
return 302 https://example.com;—— 客户端跳转,nginx 不干预后续 -
rewrite ^/old(.*)$ /new$1 redirect;—— 发送 302 响应头,流程结束 - 上游 proxy 返回 302 +
proxy_intercept_errors on—— 此时需靠error_page 302 @handle拦截,但它的跳转逻辑由你手动写(如读取 $upstream_http_location),和 recursive_error_pages 无关
真要处理多级 3XX 重定向,得这样配
想让 nginx 代理并自动跟随上游返回的多次 302(例如 OAuth 授权链、CDN 多层跳转),必须组合使用:
-
proxy_intercept_errors on;—— 允许拦截 3xx 响应 error_page 301 302 307 308 = @follow_redirect;- 在
@follow_redirect中用set $new_url $upstream_http_location;提取跳转地址 -
proxy_pass $new_url;—— 发起下一次代理请求 - 再加一层
error_page 301 302 ... = @follow_redirect;实现多跳(注意:这不是 recursive_error_pages 在起作用,而是你显式定义的 error_page 链)
这种链路没有内置层数限制,但必须自己防止无限跳转(比如加 map 判断跳转次数、域名白名单或超时终止)。
避免踩坑的关键实践
- 不要在 fallback location 里无条件 return 404 或抛异常 —— 这是触发 10 层超限的最常见原因
- 每个 error_page 指向的 location 应有兜底:用
try_files @fallback /static/err.html =404;降低二次出错概率 - 开启
error_log /var/log/nginx/error.log notice;,一旦出现循环警告能立刻捕获 - 需要规则化重写(非错误场景)?用
rewrite ... last;+if/map控制流程,别硬塞进 error_page

















