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.

3
  • Can you add the code used to forward the request to you question? Commented May 10, 2021 at 8:05
  • added a code example
    – Ann
    Commented May 10, 2021 at 9:20
  • The code you posted works as expected. Maybe you have other elements in the system (reverse proxies, rewrite valves), which duplicate the elements of your request? Commented May 11, 2021 at 5:06

1 Answer 1

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]));
1
  • 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
    Commented May 10, 2021 at 11:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.