Search code examples
spring-bootspring-webclient

Spring WebClient POST and Content Length Header for application/x-www-form-urlencoded


I am using Spring WebClient and Spring Boot 2.3.5.RELEASE to POST a request to a site that wants a Content Type of application/x-www-form-urlencoded. It keeps failing because the Content-Length header is not set. I can set that in the code, but I'm not sure how to compute the Content-Length when the Content-Type is application/x-www-form-urlencoded. The URL I am accessing is a legacy site. I saw this post Missing Content-Length header sending POST request with WebClient (SpringBoot 2.0.2.RELEASE) but it doesn't address the issue for Content-Type=application/x-www-form-urlencoded.

I executed the same request in Postman, and it works fine. In Postman if I remove the Content-Length header I get the same error I see in the code.

Please advise how to compute the Content-Length. Thank you.

Here is a snippet.

final MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
    formData.add("key 1, "value 1");
    formData.add("key 2, "value 2");
    formData.add("key 3, "value 3");
    formData.add("key 4, "value 4");

ResponseEntity<String>  resp = webClient
   .post()
   .uri("https://myurl")
   .contentType(MediaType.APPLICATION_FORM_URLENCODED)
   .header(HttpHeaders.CONTENT_LENGTH,
        String.valueOf(???))
   .body(BodyInserters.fromFormData(formData))
   .exchange()
   .flatMap(response -> response.toEntity(String.class))
   .block();

Solution

  • I have a solution. Turns out that this had nothing to do with Content-Length. I decided to try accessing the same REST endpoint with RestTemplate. I got an identical error where the target endpoint complained about missing parameters. Yet, when I accessed it with Postman or curl it worked perfectly fine.

    Instead of using BodyInserters.fromFormData with a MultiValueMap, I used BodyInserters.fromValue(bodyData). For the body data I built a String of values similar to what curl used.

    grant_type=client_credentials&client_id=123&client_secret=456&scope=myScope

    This issue is perhaps limited to the host serving this API(not a public one), but I found it interesting that RestTemplate and WebClient both failed with a standard approach for x-www-form-urlencoded, while Postman and curl worked just fine.