nginx rewrite默认丢弃查询参数,需手动处理:结尾加?可保留原始$args;显式拼接需用$arg变量并以&$args?结尾防重复;清除原始参数须避免?和$arg;复杂逻辑推荐map或location内if+rewrite。

Nginx 的 rewrite 指令本身不直接传递查询参数(query string),默认会丢弃原始 URL 中的参数。要保留或显式添加参数,必须手动处理。
保留原始查询参数
在 rewrite 规则末尾加上 ?(问号),Nginx 就会自动追加原请求的 $args(即查询字符串):
rewrite ^/old/(.*)$ /new/$1? permanent;
-
/old/test?id=123→ 重写为/new/test?id=123 -
?是关键:没有它,id=123会被丢弃
显式拼接新参数
如果需要添加、覆盖或修改参数,就别用 ?,改用 $args 变量手动构造:
rewrite ^/user/(\d+)$ /profile.php?uid=$1&source=nginx redirect;
-
/user/1001→/profile.php?uid=1001&source=nginx - 原始参数(如
/user/1001?from=web)不会自动带上,除非你显式写进规则里:
rewrite ^/user/(\d+)$ /profile.php?uid=$1&source=nginx&$args? redirect;
注意结尾的 &$args?:
-
&$args把原始参数追加到新参数后 - 结尾的
?防止 Nginx 再自动加一遍$args(否则会重复)
清除原始参数只留自定义参数
不想带任何原始参数?确保规则里不出现 $args,也不以 ? 结尾:
rewrite ^/api/v1/(.*)$ /v2/$1? redirect; # ❌ 这样会带上原始参数 rewrite ^/api/v1/(.*)$ /v2/$1 permanent; # ✅ 无 ?,无 $args → 不带任何参数
如果还要加固定参数,但不要原始参数:
rewrite ^/api/v1/(.*)$ /v2/$1?version=2.0 redirect;
用 map 或 if + rewrite 处理复杂逻辑
单纯 rewrite 难以做条件判断(比如“有某个参数才重写”)。推荐组合使用:
map $arg_ref $ref_flag {
default "";
"~^utm_" "1";
}
if ($ref_flag) {
rewrite ^/(.*)$ /track/$1? permanent;
}
或者更稳妥的方式(避免 if 在 location 外使用):
location / {
if ($args ~* "ref=([^&]+)") {
set $ref $1;
rewrite ^/(.*)$ /refer/$ref/$1? permanent;
}
}
⚠️ 注意:if 在 location 块内可用,但在 server 级别慎用;优先考虑 map + rewrite 组合。
不复杂但容易忽略细节











