nginx rewrite使用last标志会重启location匹配,若新uri再次命中含last的规则,则触发重写循环,超10次后返回500并记录“rewrite or internal redirection cycle”错误。

当 Nginx 的 rewrite 指令使用 last 标志时,会终止当前 location 的处理,重新匹配新的 location。若新 location 再次触发相同或另一条带 last 的 rewrite,就可能形成重写循环——Nginx 默认最多执行 10 次重写,超限后返回 500 错误,并在 error log 中记录 "rewrite or internal redirection cycle"。
确认是否真的发生了重写循环
检查 Nginx error log(通常位于 /var/log/nginx/error.log),搜索关键词:
rewrite or internal redirection cyclemaximum number of internal redirects reached
如果有这类日志,说明已触发保护机制;若没有但请求卡住或响应异常,需进一步验证。
定位触发 last 的 rewrite 规则
逐条检查所有 rewrite ... last; 语句,重点关注:
- 正则是否过于宽泛(例如
rewrite ^/(.*)$ /api/$1 last;匹配所有路径) - 目标路径是否仍落在某个 location 块内,且该 location 又含 rewrite 或 proxy_pass 指向自身
- location 块是否使用前缀匹配(
location /api/ { ... })而非精确匹配(location = /api/),导致 rewrite 后的新 URI 被再次捕获
验证 location 匹配逻辑是否闭环
用 curl -v 或浏览器开发者工具查看实际请求路径与响应头中的 X-Location-Matched(可自行加 log_format 输出 $location),或临时添加日志:
log_format debug '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'matched: $location';
access_log /var/log/nginx/debug.log debug;
然后观察每次 rewrite 后 Nginx 实际进入的 location 名称,看是否在两个或多个 location 间来回跳转。
修复常见死循环模式
典型错误写法及修正建议:
-
避免 rewrite 到同级 location:如
location / { rewrite ^/old/(.*)$ /new/$1 last; }+location /new/ { ... }→ 若/new/下无静态文件或未设try_files,可能再被 fallback 到/location -
用
break替代last当无需重新匹配时:如仅需改写 URI 内部路径,且后续处理仍在同一 location 内完成 - 为 rewrite 目标加前置 guard location**:例如先定义一个精确匹配的 location 拦截 rewrite 后路径,防止落入通配规则
-
启用
rewrite_log on;(配合error_log ... debug;) 查看每一步 rewrite 的输入输出,确认跳转链路
不复杂但容易忽略:last 不是跳转,而是内部重定向,整个过程都在一次请求生命周期内完成,location 匹配完全基于修改后的 URI 字符串,和浏览器地址栏无关。











