Nginx rewrite默认不继承、不拼接、不透传query string,仅重写URI路径;保留参数需显式添加?$args或以?结尾,proxy_pass末尾斜杠亦可确保透传。

rewrite 后查询参数丢失,不是“丢”,而是 Nginx 默认不继承、不拼接、不透传 query string。它只重写 URI 路径部分,原始参数不会自动追加到新路径后——这是设计行为,不是 bug。排查关键在于确认重写逻辑是否主动剥离了参数,以及后续环节(如 proxy_pass 或 redirect 响应)有没有二次干扰。
看日志:用自定义 log_format 抓住重写前后的 URI 变化
默认 access_log 不记录重写结果,需手动增强:
- 在 http 块中添加:
log_format debug '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" req="$request_uri" uri="$uri" args="$args"';
- 在对应 server 或 location 中启用:
access_log /var/log/nginx/debug.log debug; - 访问触发 rewrite 的 URL(如
/old/page?k=v),检查日志中req=(原始请求)、uri=(重写后路径)、args=(重写后参数)三者是否匹配预期
查 rewrite 配置:确认是否显式丢弃或未携带 $args
常见错误写法会直接切断参数链:
-
rewrite ^/old/(.*)$ /new/$1 permanent;→ 重定向后无参数,因未显式带上$args - 正确写法(保留参数):
rewrite ^/old/(.*)$ /new/$1?$args permanent;或更安全的rewrite ^/old/(.*)$ /new/$1? permanent;(问号结尾会自动拼接原始 args) - 若用
return,同样要带$args:return 301 /new/$1?$args; - 注意:如果 rewrite 目标以
/结尾(如/new/$1/),再加?$args会导致双问号,建议统一用?结尾方式
验代理环节:proxy_pass 是否隐式截断了 query string
当 rewrite 后走反向代理,参数丢失常发生在 proxy_pass 配置不当:
- 错误写法:
location /api { proxy_pass http://backend;→ 请求/api/v1?x=1会被代理为http://backend/v1?x=1?不,实际是http://backend+/v1?x=1,但若 backend 不支持该路径,可能出错;更常见的是路径被重写导致参数未透传 - 正确写法(保留完整 URI):
location /api/ { proxy_pass http://backend/;(注意末尾斜杠)→ 此时/api/v1?x=1会变成http://backend/v1?x=1 - 若必须用 rewrite + proxy_pass 组合,确保 rewrite 不覆盖
$args,且 proxy_pass 不做额外 URI 重写
盯响应头:Location 是否被覆盖或标准化
301/302 重定向时,浏览器靠 Location 头跳转。若该头被中间层篡改,参数就没了:
- 检查 Nginx 是否用了
proxy_redirect或add_header Location覆盖了后端返回的完整跳转地址 - CDN 或 WAF 开启“URL 标准化”时,可能自动清理带参数的 Location 值,误判为冗余内容
- 用
curl -I -v "http://yourdomain/old"直接看真实响应头,对比浏览器 Network 面板中的 Location,确认是否一致











