为什么return和rewrite的参数行为总让人困惑
很多运维在配置Nginx重定向时都踩过这个坑:明明配置了HTTP跳转HTTPS,结果跳转后URL上的查询参数全没了。比如用户访问http://example.com/page?id=123&utm_source=weixin,跳转后变成了https://example.com/page,参数丢失导致流量追踪失效、页面功能异常。
问题的根源在于Nginx的return和rewrite指令在处理查询参数时遵循不同的规则。理解这些规则,才能写出正确的配置。
return 301:参数自动保留,但要注意写法
return 301是Nginx中最简单的重定向方式。它的参数处理规则很直观:
- 使用$request_uri:自动保留完整的原始URI,包括路径和查询参数
- 使用$uri:只保留路径,查询参数会丢失
正确的写法
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}这样配置后,http://example.com/page?id=123会跳转到https://example.com/page?id=123,参数完整保留。
错误的写法
return 301 https://$host$uri; # 参数会丢失!因为$uri变量只包含路径部分,不包含查询字符串。
rewrite:参数行为取决于问号
rewrite指令的参数处理规则完全不同,核心在于问号(?)的特殊含义。
规则一:不带问号,参数自动追加
如果rewrite的目标URL不带问号,原始查询参数会自动追加到目标URL后面:
rewrite ^/(.*)$ https://example.com/$1 permanent;访问http://example.com/page?id=123,跳转后变成https://example.com/page?id=123,参数保留。
规则二:带问号,参数被替换
如果目标URL带问号,问号后面的内容会完全替换原始查询参数:
rewrite ^/(.*)$ https://example.com/$1?new=param permanent;访问http://example.com/page?id=123,跳转后变成https://example.com/page?new=param,原参数丢失。
规则三:问号后为空,参数被清空
如果只想清空查询参数,可以在目标URL后面加一个空的问号:
rewrite ^/(.*)$ https://example.com/$1? permanent;这样跳转后URL就变成https://example.com/page,没有任何参数。
return和rewrite参数行为对比表
| 指令 | 写法示例 | 参数行为 |
|---|---|---|
| return 301 | return 301 https://$host$request_uri | 保留全部参数 |
| return 301 | return 301 https://$host$uri | 参数丢失 |
| rewrite | rewrite ^ https://example.com permanent; | 保留全部参数 |
| rewrite | rewrite ^ https://example.com?x=1 permanent; | 替换为新参数 |
| rewrite | rewrite ^ https://example.com? permanent; | 清空所有参数 |
什么时候用return,什么时候用rewrite
推荐使用return的场景
- 整站HTTP跳HTTPS:最简单最直接的方式
- 域名整体迁移:如
example.com跳www.example.com - 不需要正则匹配:目标URL固定,逻辑简单
推荐使用rewrite的场景
- 需要正则捕获URL的一部分:如
/old/(.*)跳/new/$1 - 需要修改或替换查询参数:如添加、删除、修改特定参数
- 复杂的URL重写逻辑:需要多层条件判断
实战案例:UTM参数丢失排查与修复
某运营反馈,微信推广链接http://example.com/landing?utm_source=weixin&utm_campaign=spring跳转HTTPS后,GA4后台无法追踪流量来源。
问题配置
server {
listen 80;
server_name example.com;
rewrite ^/(.*)$ https://example.com/$1? redirect;
}问题在于末尾多了一个?,导致所有查询参数被清空。
修复方案
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}改用return 301配合$request_uri,简洁可靠,参数完整保留。
验证参数是否保留的正确方法
不要用浏览器测试,浏览器会自动跟跳转,不方便观察。用curl的-v参数查看原始响应:
curl -v http://example.com/page?id=123查看响应头中的Location字段,确认目标URL是否包含查询参数。
总结
Nginx重定向参数处理的核心规则:
return 301用$request_uri保留参数,用$uri会丢参数rewrite不带问号自动追加参数,带问号会替换参数- 整站跳转首选
return,URL重写用rewrite - 上线前用curl验证Location头,确保参数正确
掌握这些规则,Nginx重定向配置再也不踩坑。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论