0

Nginx rewrite问号含义解析:为什么你的查询参数总是莫名消失?

2026.05.27 | youres | 10次围观

前言:一个问号引发的血案

写Nginx重定向规则的时候,你有没有遇到过这种情况:明明配置了rewrite,跳转后URL里的查询参数却凭空消失了?utm_source、page、id这些参数,一个都不剩。折腾半天,最后发现问题出在rewrite规则里一个小小的问号(?)上。

今天这篇文章,我就把Nginx rewrite中问号的含义彻底讲清楚,让你以后写重定向规则不再踩坑。

一、rewrite指令的基本语法

先复习一下rewrite的基本格式:

rewrite regex replacement [flag];

三个部分:

  • regex:正则表达式,匹配请求的URI(不含查询参数)
  • replacement:替换后的目标地址
  • flag:可选,控制后续处理行为(last、break、redirect、permanent)

关键点在于:rewrite只处理$uri部分,不包含问号后面的查询字符串。查询参数的附加,需要你显式处理。

二、问号在replacement中的特殊含义

这是本文的核心。在rewrite的replacement部分,问号有两个截然不同的行为:

1. 没有问号 → 自动追加原查询参数

如果你的replacement里不包含问号,Nginx会自动把原始请求的查询参数追加到目标URL后面。

# 请求: /old?page=2&sort=date
rewrite ^/old$ /new last;
# 结果: /new?page=2&sort=date  ← 参数自动保留了!

这是Nginx的默认行为,很多人不知道,所以有时候参数"莫名其妙"还在。

2. 有问号 → 清空原查询参数,使用新的

一旦replacement里出现了问号,Nginx就认为你要自己控制查询参数,于是丢弃所有原始参数,只保留问号后面的内容。

# 请求: /old?page=2&sort=date
rewrite ^/old$ /new?status=ok last;
# 结果: /new?status=ok  ← 原参数page=2&sort=date全没了!

这就是参数丢失的最常见原因——你无意中在replacement里加了个问号,原参数就被清空了。

三、问号后面什么都不写:彻底清空参数

有时候我们确实想清空所有查询参数,怎么做?

rewrite ^/old$ /new? last;
# 请求: /old?page=2&sort=date
# 结果: /new  ← 干干净净,没有问号,没有参数

问号后面什么都不跟,Nginx会把原始查询参数全部丢弃,目标URL也不会带问号。

这种用法在规范化URL时很有用——去掉无意义的跟踪参数,让URL更干净。

四、保留原参数的正确姿势

既然问号会清空原参数,那想保留原参数该怎么做?有三种常用方法:

方法1:不在replacement中写问号

# 最简单,不写问号就自动追加
rewrite ^/old$ /new last;

方法2:用$is_args$args拼接

当你需要在replacement中写问号,又想保留原参数时:

rewrite ^/old$ /new?status=ok$is_args$args last;
# 请求: /old?page=2
# 结果: /new?status=ok&page=2

这里解释一下:

  • $is_args:如果原始请求有查询参数,值为?;没有则为空
  • $args:原始请求的查询参数值(不含问号)

所以$is_args$args就是"有参数就带上?加参数,没参数就什么都不加"。

方法3:用$request_uri直接取完整路径

如果是HTTP跳HTTPS这种场景,用return 301更简单:

return 301 https://$host$request_uri;

$request_uri包含完整的URI和查询参数,一个变量搞定。

五、常见坑与实战案例

坑1:rewrite带问号导致UTM参数丢失

# 错误写法
rewrite ^/blog/(.*)$ /article?slug=$1 last;
# 请求: /blog/hello?utm_source=wechat
# 结果: /article?slug=hello  ← utm_source没了!

# 正确写法
rewrite ^/blog/(.*)$ /article?slug=$1&$args last;
# 或者更安全的写法
rewrite ^/blog/(.*)$ /article?slug=$1$is_args$args last;

坑2:问号位置不当导致URL格式异常

# 危险:当原始请求没有参数时
rewrite ^/old$ /new?$args last;
# 请求: /old(无参数)
# 结果: /new?  ← 末尾多了个问号

# 安全:用$is_args判断
rewrite ^/old$ /new$is_args$args last;

坑3:多次rewrite参数被反复覆盖

如果配置了多条rewrite规则,每条带问号的rewrite都会重新设定查询参数:

rewrite ^/a$ /b?x=1 last;   # 第1次:参数变为x=1
rewrite ^/b$ /c?y=2 last;   # 第2次:参数变为y=2,x=1丢了

遇到这种情况,需要在每一步都手动拼接参数,或者改用set指令来累积参数。

六、总结:一张表搞懂问号行为

replacement写法原始参数结果URL说明
/new?page=2/new?page=2无问号,自动追加原参数
/new?status=ok?page=2/new?status=ok有问号,原参数被丢弃
/new??page=2/new问号后为空,彻底清空参数
/new?status=ok$is_args$args?page=2/new?status=ok&page=2手动拼接,保留原参数
/new$is_args$args(无参数)/new无参数时不带问号

相关文章推荐

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论
882文章数 0评论数
作者其它文章