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 状态码本身当作参数丢失的证据。
常见问题(FAQ)
Q:参数被编码/解码了吗?
A:不带 URI 的 proxy_pass 通常转发原请求 URI;路径经 rewrite 修改后可能传递规范化后的完整 URI。带 URI 的替换按规范化路径进行;不能把路径与查询串的编码处理混为一谈,应测试实际特殊字符。
Q:后端说参数乱码?
A:确认客户端→Nginx→后端的编码一致(UTF-8),Nginx 默认不改编码,乱码多在应用解码环节。
Q:怎么按参数值分流到不同后端?
A:可在 http 级 map 中把允许的参数值映射到预定义后端,再在 location 中引用;不要把任意请求参数直接作为上游地址,变量 proxy_pass 的解析和 URI 语义需另行验证。