Nginx 的 proxy_pass 会把 query string 参数转发给后端吗?
默认会。proxy_pass 自动携带原始查询串;重写 URL(rewrite)或 proxy_pass 带 URI 部分时需注意 $args 与 is_args 的保留。自定义参数用 $args、$arg_ 变量操作。
答案:默认会自动转发——proxy_pass http://backend; 时,客户端的查询串(?a=1&b=2)原样带给后端。需要自己操心的是两种"例外":proxy_pass 后面带了 URI 部分(如 proxy_pass http://backend/api;)的重写行为,以及 rewrite 指令默认会丢弃/重建参数。
默认行为:透传
location / {
proxy_pass http://127.0.0.1:8080;
}
请求 /search?q=nginx&page=2 → 后端收到 /search?q=nginx&page=2。无需任何配置。
注意点一:proxy_pass 带 URI 部分
location /api/ {
proxy_pass http://127.0.0.1:8080/; # 注意结尾的 /
}
- 带 URI(哪怕是
/):匹配前缀被替换——/api/users?x=1→/users?x=1,参数仍保留 - 不带 URI:
/api/users?x=1→/api/users?x=1原样转发
两种写法参数都不会丢,丢的是路径前缀,别搞错。
注意点二:rewrite 的参数处理
rewrite ^/old/(.*)$ /new/$1; # 默认保留原参数
rewrite ^/old/(.*)$ /new/$1?; # 结尾 ? 表示丢弃原参数
rewrite ^/old/(.*)$ /new/$1?type=fixed; # 自己的参数会替换掉原参数!
第三条里原 query string 被替换——想合并要显式带上 $args:
rewrite ^/old/(.*)$ /new/$1?type=fixed&$args?; # 不推荐这么绕
更干净的做法是用变量操作(见下)。
自定义/修改参数
location / {
set $args $args&source=proxy; # 追加参数
# 或读取单个参数
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-User-Id $arg_uid; # 取 ?uid= 的值放进 header
}
$args:完整查询串$arg_名字:单个参数值set $args ...可整体改写
观测云对照
参数正确性从链路验证。 反代后参数丢失导致的后端 400,在观测云 APM 调用链里能看到后端实际收到的完整 URL,与前端请求比对即刻定界是代理层还是应用层问题。
常见问题(FAQ)
Q:参数被编码/解码了吗?
A:proxy_pass 透传时是规范化后的 URI;带 URI 部分替换时会做 URL 解码再编码,特殊字符场景注意测试。
Q:后端说参数乱码?
A:确认客户端→Nginx→后端的编码一致(UTF-8),Nginx 默认不改编码,乱码多在应用解码环节。
Q:怎么按参数值分流到不同后端?
A:if ($arg_env = test) { proxy_pass http://test-backend; },或更规整地用 map 指令映射 upstream。