Nginx 301重定向需精准映射旧路径(如/admin.php?act=edit&id=5)到新RESTful路径(如/admin/edit/5),用rewrite+permanent在server块顶层匹配参数、避免循环,辅以location前缀优化和兜底规则,并严格验证状态码、参数透传与日志。

老旧框架升级时,Nginx 的 301 重定向核心是把旧控制层路径(如 /admin.php?act=edit&id=5 或 /index.php/controller/action)精准、无损地映射到新 RESTful 路径(如 /api/v2/admin/edit/5 或 /admin/edit/5),同时保留关键参数、避免循环跳转、不依赖后端响应。
用 rewrite + permanent 匹配并提取关键参数
旧框架常靠查询参数驱动逻辑,需用正则捕获 ID、动作名等核心字段,再拼成新路径。规则必须写在 server 块顶层,不能嵌套在 location 内,否则可能被 location 优先级覆盖而失效。
- 匹配 PHP 入口带参数:
rewrite ^/admin\.php\?act=(\w+)&id=(\d+)$ /admin/$1/$2 permanent; - 匹配传统 index.php 路由:
rewrite ^/index\.php/(\w+)/(\w+)(?:\?.*)?$ /$1/$2 permanent; - 兼容大小写与下划线:
rewrite ^/user/profile/([a-z0-9_-]+)$ /users/$1 permanent;
按目录前缀批量迁移控制路径
若旧路径有统一前缀(如 /cgi-bin/、/legacy/、/php/),用 location ^~ 配合 rewrite 更高效,减少全局正则开销。
location ^~ /legacy/api/ { rewrite ^/legacy/api/(.*)$ /v2/api/$1 permanent; }location ^~ /php/ { rewrite ^/php/(.*)$ /app/$1 permanent; }- 注意:结尾的
permanent明确发出 301 状态码,不可省略
兜底与防错:避免 404 和跳转循环
不是所有旧路径都能一一映射,需设置 fallback 机制,防止用户或爬虫撞上未覆盖的 URL。
- 对无法结构化映射的请求,先跳到通用入口页:
rewrite ^/old-control/.*$ /migration-notice permanent; - 用
if做简单判断(仅限必要场景):if ($args ~* "token=") { return 301 /auth/login?$args; } - 禁止用
if ($request_uri ~ ...)做复杂判断——易引发循环或性能问题
验证与上线前必须做的三件事
配置生效前,重点验证是否真正“平滑”:参数没丢、状态码正确、没有二次跳转。
- 用
curl -I http://old-site/legacy/user?id=123检查响应头是否含HTTP/1.1 301 Moved Permanently和准确的Location - 确认新地址中
id=123是否完整透传(或按规则转换),不因漏写$args或误用$uri导致参数丢失 - 上线后盯 5 分钟 access 日志,筛选仍返回 404 的旧路径,快速补漏规则


















