Nginx rewrite循环本质是rewrite指令反复触发致内部跳转超限(默认10次)返回500错误,主因是rewrite last未终止匹配流程使请求重回同一location;应改用break、精确location匹配、return替代或启用rewrite_log定位。

Nginx 的 rewrite 规则本身不直接处理“错误”,它只负责 URL 重写或跳转;真正的错误响应(如 404、500)由 error_page 指令控制。要让 rewrite 更健壮、避免因规则引发意外错误(比如循环重定向、空匹配、死跳转),关键在于:**合理组合 rewrite + return + error_page,并用条件判断规避非法请求**。
用 return 替代危险的 rewrite ... redirect
当目的只是返回固定状态码(如 403、404、410),优先用 return,它不触发 location 匹配,不会造成重定向循环或隐式内部跳转:
-
return 404;—— 立即返回 404,不执行后续 rewrite 或 proxy -
return 410 "Gone";—— 返回 410 并带自定义响应体 -
return 301 https://$host$request_uri;—— 安全的全站 HTTPS 跳转(注意变量安全)
用 if + return 做前置校验
rewrite 前先检查 URI、参数或头信息是否合法,不满足就提前终止,避免无效重写导致 500 或 404 泛滥:
-
if ($args ~ "phpinfo") { return 403; }—— 拦截敏感查询参数 -
if ($request_uri ~ "^/wp-.*") { return 404; }—— 屏蔽 WordPress 目录扫描 -
if ($http_user_agent ~ "(sqlmap|nikto)") { return 444; }—— 静默丢弃恶意 UA(444 是 Nginx 特有“关闭连接”码)
用 error_page 统一接管 rewrite 引发的错误
rewrite 中的 break、last 或 redirect 若匹配失败或目标 location 不存在,可能最终落到 404。此时可自定义错误页并记录上下文:
-
error_page 404 /404.html;—— 静态页 -
error_page 404 = @fallback;—— 转给 named location 做兜底(如反向代理到旧系统) -
error_page 400 403 405 406 408 410 411 413 414 417 /error.html;—— 批量映射常见客户端错误
避免 rewrite 循环的硬性约束
以下写法极易导致 301/302 循环(浏览器报 ERR_TOO_MANY_REDIRECTS):
- ❌
rewrite ^/(.*)$ https://$host/$1 permanent;—— 没判断协议,HTTPS 请求也会再跳一次 - ✅ 应改为:
if ($scheme = http) { return 301 https://$host$request_uri; } - ❌
rewrite ^/old/(.*)$ /new/$1 last;且location /new/ { ... }内部又含同名 rewrite - ✅ 加
break或确保/new/location 不再重写,或用location ^~ /new/阻止正则匹配干扰


















