验证nginx rewrite重定向需用curl -i/-l检查状态码、location头及跳转链,禁用缓存并模拟host头;重点排查last/break/redirect flag误用导致的循环,结合access_log和nginx -t确认location匹配与配置生效。

验证生产环境中的 Nginx rewrite 重定向逻辑,不能只看配置是否“能跑”,关键是要确认浏览器和客户端实际收到的响应行为是否符合预期——尤其是状态码、Location 头、跳转路径是否准确,且不引入循环或缓存干扰。
用 curl 模拟真实请求,抓取原始响应头
这是最直接、最可靠的方式。绕过浏览器缓存,查看 Nginx 真实返回:
- 检查 301/302 跳转: curl -I http://old.example.com/path 观察输出中是否有 HTTP/1.1 301 Moved Permanently 或 302 Found,以及 Location: 后的地址是否正确(注意协议、域名、路径、尾部斜杠)
- 跟踪跳转链(最多 5 层): curl -L -I http://old.example.com/path -L 表示自动跟随重定向,-I 只取响应头。可看到每一步的状态码和 Location,快速识别是否多跳、错跳或死循环
- 禁用缓存并携带 Host 头(模拟特定域名): curl -I --no-cache -H "Host: old.example.com" http://192.168.1.100/path 适用于未切 DNS 的灰度服务器或 hosts 绑定测试,避免受 DNS 或 CDN 干扰
检查 rewrite 循环与 flag 使用是否合理
rewrite 隐含最多 10 次内部重试机制,配置不当极易触发 500 错误。验证重点是:是否因 flag 误用导致反复匹配。
- 若使用 redirect 或 permanent,跳转由客户端发起,Nginx 不再处理后续 rewrite —— 安全但需确保 replacement 地址绝对可达
- 若使用 last,Nginx 会重启 location 匹配,可能再次命中同一 rewrite 规则(尤其 regex 过宽,如 ^/.*$),造成隐式循环
- 若使用 break,匹配后立即终止当前块内所有 rewrite,适合内部路径改写(非跳转场景);在重定向需求中慎用,否则可能跳转失效
- 验证方法:临时把疑似规则的 flag 改为 break,再用 curl -I 测试,若状态码变成 200/404 而非 301/302,说明原 flag(如 last)确实在触发重复匹配
排除浏览器和中间件缓存干扰
301 重定向会被浏览器和 CDN 强力缓存,一次错误配置可能长期生效,验证前必须清理干扰源:
- 浏览器侧:用无痕窗口测试,或加随机参数强制绕过缓存,例如 curl -I "http://old.example.com/path?v=$(date +%s)"
- CDN 或反向代理层(如 Cloudflare、SLB):确认其未缓存 301 响应;可临时关闭 CDN 缓存,或在请求头中加 Cache-Control: no-cache 并观察响应头是否带 CF-Cache-Status: DYNAMIC 等标识
- 服务端日志验证:打开 Nginx access_log 和 error_log,对目标 URL 发起请求,检查日志中是否只记录 1 条 301 日志(而非连续多条),可辅助判断是否发生循环
结合 location 匹配顺序做边界验证
rewrite 生效前提是它所在的 location 被正确匹配。很多“不跳转”问题其实源于 location 未命中。
- 确认请求 URI 是否落入预期 location 块:比如 rewrite 写在 location /old/ { ... } 中,但请求是 /old(无尾斜杠),而该 location 是精确匹配 = /old/,那就根本不会执行
- 用 nginx -T 输出完整生效配置,搜索对应 server_name 和 location,确认 rewrite 行确实存在且位置合理(不在 if 嵌套过深或被其他 location 覆盖)
- 添加临时日志标记:在目标 location 内加 access_log /var/log/nginx/rewrite-debug.log;,再请求验证日志是否写入,即可确认 location 是否触发











