2

We have a Controller running on tomcat 8.5.32 which receives a POST request with query params /{path_param}/issue?title=4&description=5 request body is empty

Then controller redirects this request to Spring Boot microservice with tomcat 9.0.27. At line

CloseableHttpResponse result = httpClient.execute(request);

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

But when it arrives to microservice parameters are duplicated (title=[4,4]&description=[5,5]).

This is the code which redirects request to microservice

  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) {
        ...
    }
}

I found that there was similar issue with jetty and it was fixed but did not find anything related to tomcat - and how it can be fixed. I saw also this topic whith suggestion how to handle duplicated parameters in spring boot but i am wondering if anyone else experienced same issue and how did you resolve it if yes.

Ann
  • 193
  • 1
  • 1
  • 12

1 Answers1

0

It's not a bug, it's a feature present in every servlet container.

The Servlet API does not require for the request parameters to have unique names. If you send a POST request for http://example.com/app/issue?title=1&description=2 with a body of:

title=3&description=4

then each parameter will have multiple values: title will have values 1 and 3, while description will have values 2 and 4 in that order:

Data from the query string and the post body are aggregated into the request parameter set. Query string data is presented before post body data. For example, if a request is made with a query string of a=hello and a post body of a=goodbye&a= world, the resulting parameter set would be ordered a=(hello, goodbye, world).

(Servlet specification, section 3.1)

If you want to copy just the first value of the parameters use:

httpServletRequest.getParameterMap()//
                  .forEach((k, v) -> uriBuilder.addParameter(k, v[0]));
Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43
  • 2
    Thank you Piotr foryour response, body is empty in our case, at the line CloseableHttpResponse result = httpClient.execute(request); request.getURI().getQuery() contains &title=1&description=2 but when it arrives to microservice, values are duplicated. – Ann May 10 '21 at 11:49