nginx 中需用 if + rewrite 或 location + return 实现旧动态链接到新版伪静态页的 301 跳转,关键在于通过正则匹配 $args 提取 tid 参数并清空查询字符串,再配合反向 rewrite 支持伪静态访问。

Nginx 中将旧版论坛的动态 ID 链接(如 forum.php?mod=viewthread&tid=123)301 永久重定向到新版伪静态页(如 /thread-123.html),关键在于精准匹配带参数的 URI 并提取 ID,再构造目标路径。不能用 return 301 简单拼接(因 $request_uri 会原样保留查询字符串),必须用 rewrite + permanent 标志。
以下为实用、可直接部署的配置逻辑:
✅ 匹配并提取动态链接中的 tid 参数
适用于 Discuz! 等常见论坛的旧链接格式:/forum.php?mod=viewthread&tid=123 或 /viewthread.php?tid=123
if ($args ~* "tid=(\d+)") {
set $tid $1;
rewrite ^/forum\.php$ /thread-$tid.html? permanent;
}
或更通用写法(兼容多种入口文件):
if ($args ~* "tid=(\d+)") {
set $tid $1;
rewrite ^/(forum|viewthread)\.php$ /thread-$tid.html? permanent;
}
⚠️ 注意:
?在末尾用于清空原始查询参数,避免跳转后变成/thread-123.html?tid=123。
✅ 同时支持多参数场景(如含 page、extra)
若旧链接形如:/forum.php?mod=viewthread&tid=456&page=2&extra=page%3D1
可只提取 tid,忽略其余参数:
if ($args ~* "tid=(\d+)") {
set $tid $1;
rewrite ^/forum\.php$ /thread-$tid.html? permanent;
}
Nginx 的 if + rewrite 会优先匹配并执行,$args 是完整查询字符串,正则 tid=(\d+) 能准确定位。
✅ 更健壮的写法:用 location + rewrite 替代 if(推荐)
if 在 location 外使用有局限(如不支持嵌套、部分变量不可用),更稳妥方式是放在 location 块中,并配合 try_files 或显式匹配:
location = /forum.php {
if ($args ~* "tid=(\d+)") {
return 301 /thread-$1.html;
}
return 404;
}
location = /viewthread.php {
if ($args ~* "tid=(\d+)") {
return 301 /thread-$1.html;
}
return 404;
}
✅ 优势:
-
return 301性能更高、语义清晰; -
= /forum.php是精确匹配,避免误触其他 PHP 文件; -
$1直接引用正则捕获组,无需set变量; - 无匹配时返回 404,防止无效跳转。
✅ 配合新版伪静态规则共存(不冲突)
确保新版页面能正常访问,需在同 server 块中添加反向 rewrite(内部转发):
location ~ ^/thread-(\d+)\.html$ {
rewrite ^/thread-(\d+)\.html$ /forum.php?mod=viewthread&tid=$1 last;
}
这样:
- 用户访问
/thread-123.html→ 内部映射到旧脚本处理(伪静态生效); - 用户访问
/forum.php?tid=123→ 301 跳转到/thread-123.html(SEO 友好)。
配置完成后:
- 运行
nginx -t检查语法; - 执行
nginx -s reload生效; - 用
curl -I http://yoursite.com/forum.php?tid=123验证返回301及Location: /thread-123.html。
不复杂但容易忽略细节











