经纬志
首页 / 实战手册 / 服务端与发布

代理转发后,WMS 的查询参数全丢了

先看结论

直连 GeoServer 正常,经过公司网关后所有请求都变成“缺少 LAYERS 参数”,服务端日志里看不到 BBOX。

最后验证 2026-11-03 · 多技术栈 · GeoServer 2.25 · 更新 2026-10-29 · 引用本文

现象

浏览器请求的 URL 参数齐全,GeoServer 返回的参数却只剩一部分,或者完全是空的:

<ServiceException code="MissingParameterValue">
  Could not find the LAYERS parameter
</ServiceException>

在 Nginx 访问日志里把 $request 打出来,参数是完整的, 说明丢失发生在转发阶段。

原因

proxy_pass 后面带 URI 时,Nginx 会用这个 URI 替换掉原始请求的路径与查询串。 例如 proxy_pass http://backend/wms;,原请求的 ?SERVICE=WMS&... 会被丢弃。

使用 rewrite ... ? 显式给了新的查询串时,也会覆盖原参数; 而 rewrite 里如果写了 ? 结尾,同样会清空。 另一类问题是参数被二次编码,& 变成 &amp;, 后端只解析到第一个参数。

排查过程

在 location 里临时打开请求日志,对比进入与转发的内容:

location /geoserver/ {
    proxy_pass http://127.0.0.1:8080/geoserver/;
    access_log /var/log/nginx/gis_proxy.log custom;
}

# log_format custom '$remote_addr "$request" -> $upstream_addr $upstream_status';

也可以把上游收到的完整 URI 打出来:

add_header X-Debug-Upstream $upstream_http_x_original_uri always;

解决方案

需要保留原始路径与参数时,proxy_pass 不要带 URI, 只写上游主机与端口:

location /geoserver/ {
    proxy_pass http://127.0.0.1:8080;      # 正确:不带 /geoserver
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

必须改写路径时,用命名捕获并显式带上 $is_args$args:

location /gis/ {
    rewrite ^/gis/(.*)$ /geoserver/$1 break;
    proxy_pass http://127.0.0.1:8080$uri$is_args$args;
}

前端拼接 URL 时不要手动 encodeURIComponent 整个查询串, 只对参数值编码,避免 & 被转义:

var params = new URLSearchParams({
  SERVICE: 'WMS',
  VERSION: '1.1.1',
  REQUEST: 'GetMap',
  LAYERS: 'workspace:roads',
  BBOX: bbox.join(','),
  WIDTH: 512,
  HEIGHT: 512,
  SRS: 'EPSG:3857',
  FORMAT: 'image/png'
});

var url = '/geoserver/wms?' + params.toString();

验证

用 curl 经过代理请求,GeoServer 的访问日志里能看到完整的 LAYERS、BBOX、WIDTH。 GetMap 返回 PNG 而不是 XML 报错。 带多个参数的请求与只带一个参数的请求都正常。

一句话规则:proxy_pass 末尾有没有斜杠,决定路径是否被替换。 带 URI 就替换,不带就原样转发。参数丢失几乎都能从这一条找到原因。

引用本文

经纬志(2026)。《代理转发后,WMS 的查询参数全丢了》。https://www.jingweizhi.com/cookbook/nginx-proxy-drop-params.html(访问日期 2026-11-03)。