【问题标题】:request parameters got duplicated when forwarded between two tomcats请求参数在两个 tomcat 之间转发时重复
【发布时间】:2021-05-10 07:54:42
【问题描述】:

我们有一个在 tomcat 8.5.32 上运行的控制器,它接收带有查询参数的 POST 请求 /{path_param}/issue?title=4&description=5 请求正文为空

然后控制器将此请求重定向到带有 tomcat 9.0.27 的 Spring Boot 微服务。 在行

CloseableHttpResponse result = httpClient.execute(request);

request.getURI().getQuery()等于&title=1&description=2

但是当它到达微服务时,参数是重复的(title=[4,4]&description=[5,5])。

这是将请求重定向到微服务的代码

  private static <T, U> T executePostRequest(String url, U body, HttpServletRequest httpServletRequest, Function<String, T> readValueFunction) {

    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
        URIBuilder uriBuilder = new URIBuilder(url);
        httpServletRequest.getParameterMap().forEach((k, v) -> Arrays.stream(v).forEach(e -> uriBuilder.addParameter(k, e)));
        HttpPost request = new HttpPost(uriBuilder.build());
      

        CloseableHttpResponse result = httpClient.execute(request);
        String json = EntityUtils.toString(result.getEntity(), "UTF-8");

        handleResultStatus(result, json);

        return readValueFunction.apply(json);
    } catch (IOException | URISyntaxException e) {
        ...
    }
}

我发现jetty 存在类似问题,并且已修复,但未找到与 tomcat 相关的任何内容 - 以及如何修复它。 我还看到this topic 提出了如何在 Spring Boot 中处理重复参数的建议,但我想知道是否有其他人遇到过同样的问题,如果是,您是如何解决的。

【问题讨论】:

  • 您能否添加用于将请求转发给您的问题的代码?
  • 添加了代码示例
  • 您发布的代码按预期工作。也许您的系统中有其他元素(反向代理、重写阀门)与您的请求元素重复?

标签: spring-boot tomcat query-string


【解决方案1】:

这不是一个错误,它是每个 servlet 容器中存在的一个特性。

Servlet API 不要求请求参数具有唯一名称。如果您向 http://example.com/app/issue?title=1&amp;description=2 发送 POST 请求,其正文为:

title=3&description=4

那么每个参数将有多个值:title 将有值13,而description 将有值24 按顺序排列:

来自查询字符串和帖子正文的数据被聚合到请求中 参数集。查询字符串数据显示在帖子正文数据之前。例如,如果 使用 a=hello 的查询字符串和 a=goodbye&a= 的帖子正文发出请求 world,生成的参数集将被排序为 a=(hello, goodbye, world)。

Servlet specification,第 3.1 节)

如果您只想复制参数的第一个值,请使用:

httpServletRequest.getParameterMap()//
                  .forEach((k, v) -> uriBuilder.addParameter(k, v[0]));

【讨论】:

  • 谢谢 Piotr 的回复,在我们的例子中,body 是空的,在 CloseableHttpResponse result = httpClient.execute(request); request.getURI().getQuery() 包含 &title=1&description=2 但是当它到达微服务时,值是重复的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-09
  • 2023-03-15
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
相关资源
最近更新 更多