2026.05.30 | youres | 3次围观
为什么rewrite会丢失参数?
配置Nginx rewrite时,很多人遇到一个奇怪问题:重定向后URL里的查询参数(比如 ?utm_source=xxx)不见了。这不是bug,而是Nginx的有意设计。
核心原因:rewrite的替换字符串中一旦出现问号 ?,原请求的查询参数就会被清空。这是最常见的踩坑点。
# 这个规则会把原参数清空!
rewrite ^/old/(.*)$ /new/= last;
明白了原理,下面看4种保留参数的方法。
方法1:用 $is_args 拼接参数
这是最常用的方法。$is_args 的值取决于是否有参数:有参数时是 ?,没有时为空字符串。$args 是完整的查询字符串(不含问号)。
rewrite ^/old/(.*)$ /new/$is_args` last;
效果:原请求 /old/page?utm_source=google → /new/page?utm_source=google,无参数时不会多出多余的 ?。
优点:简单直观,适合大多数场景。
缺点:追加新参数时要注意避免双重问号。
方法2:替换字符串不加问号(自动保留原参数)
Nginx有个隐藏特性:如果rewrite替换字符串中不含问号,原查询参数会被自动追加到新URL后面。
# 不含?,Nginx自动保留原参数
rewrite ^/old/(.*)$ /new/ last;
优点:写法最简洁,不需要手动拼接。
缺点:无法选择性保留或覆盖特定参数。
方法3:用 try_files 替代rewrite
如果需求只是"请求转发到某个文件",try_files 比rewrite更合适。它是内部重定向,不改地址栏,也不会丢失查询参数。
location / {
try_files $uri $uri/ /index.html;
}
SPA应用常用这个配置,整个过程中 ?xxx=yyy 始终保留。
优点:不丢参数,性能比rewrite好(无需正则匹配)。
缺点:只能做文件存在性检查,不能做复杂URL重写。
方法4:用 map 指令精细控制参数
需要条件性地保留、删除或修改查询参数时,map 是最强大的工具。它在 http 块中定义映射规则,根据条件动态生成参数字符串。
http {
map $args $filtered_args {
~^(.*)(utm_source=[^&]*)(.*)$ $2;
default $args;
}
}
server {
rewrite ^/old/(.*)$ /new/$filtered_args last;
}
优点:最灵活,可实现复杂的参数过滤逻辑。
缺点:配置复杂,需放在 http 块,不适合快速修改。
4种方法对比
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
$is_args` | 精确控制参数拼接 | 简单直观 | 追加新参数需防双重问号 |
| 替换字符串不含? | 简单重定向,保留全部原参数 | 写法最简洁 | 无法覆盖或删除指定参数 |
try_files | SPA、静态文件转发 | 不丢参数,性能好 | 不能做复杂URL重写 |
map 指令 | 条件过滤、精细控制参数 | 最灵活强大 | 配置复杂 |
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论