Nginx目录级rewrite可高效处理老旧网站URL迁移:通过location+rewrite实现301/302重定向,支持正则捕获、map映射和try_files兜底,兼顾性能、可控性与SEO。

老旧网站改版后,常有大量历史URL失效,直接返回404会影响SEO和用户体验。Nginx 的 rewrite 指令可在目录级(location 块内)精准匹配旧路径,将其平滑重定向到新地址,无需后端参与,性能高、响应快。
用 location + rewrite 实现目录级重定向
核心思路是:在特定 URL 前缀(如 /old/)的 location 块中,用 rewrite 指令匹配并替换路径,配合 redirect 或 permanent 发送 HTTP 301/302 响应。
-
匹配旧目录下的所有请求:例如将
/old/article?id=123重定向为/news/123,可写:location ^~ /old/ {<br> rewrite ^/old/article$ /news/$arg_id? permanent; -
支持正则捕获与变量引用:如旧链接形如
/old/2020/05/post-abc.html,想转为/blog/abc:location ^~ /old/ {<br> rewrite ^/old/\d{4}/\d{2}/post-(.+)\.html$ /blog/$1 permanent; -
注意末尾斜杠与匹配优先级:使用
^~前缀可避免正则 location 干扰;若旧链接带查询参数需保留,结尾加?可清空原参数,不加则自动继承。
避免循环重定向和 404 的关键细节
错误配置易导致跳转链过长甚至死循环(如 A→B→A),或因路径未覆盖而漏掉部分链接。
-
先写精确匹配,再写泛匹配:把高频、确定的旧路径(如
/old/about.html)单独写成location = /old/about.html,再用泛匹配兜底,防止规则误伤。 -
测试 rewrite 结果是否符合预期:用
curl -I查看响应头中的Location字段;也可临时加return 200 "rewritten to: $request_uri";辅助调试。 -
区分内部重写与外部重定向:仅修改 URI 不发跳转用
rewrite ... last;(内部处理);要让用户浏览器地址栏变化,必须用redirect(302)或permanent(301)。
批量迁移时的实用技巧
当旧链接数量大、规律复杂(如含年月分类、ID 映射、编码差异),纯手工写 rewrite 效率低且易错。
-
用 map 指令做静态映射表:适合 ID 到新 slug 的一对一关系,例如:
map $args $new_path {<br> default "";<br> "id=101" "/product/apple";<br> "id=102" "/product/orange";<br>}<br>location = /old/item.php {<br> if ($new_path) { return 301 $new_path; }<br>} -
结合 try_files + rewrite 实现“存在才跳”逻辑:例如只对真实存在的旧文章路径跳转,不存在的直接 404:
location ^~ /old/ {<br> try_files $uri @rewrite_old;<br>}<br>location @rewrite_old {<br> rewrite ^/old/(.+)$ /new/$1 permanent;<br>} -
日志中标记重定向流量便于追踪:在 rewrite 所在 location 中加
access_log /var/log/nginx/rewrite.log main if=$args;(按需启用)。
目录级 rewrite 是老旧链接治理中最轻量、最可控的方式。理清匹配顺序、善用正则捕获、配合 map 或 try_files,就能在不改动代码的前提下,把用户和搜索引擎稳稳接住。不复杂但容易忽略细节。

















