Home > Enterprise >  415 Unsupported Media Type from POST
415 Unsupported Media Type from POST

Time:05-06

I need to create a POST call with Spring/Webclient which does work fine with curl.

POSTDATA="{\"subject\":\"CN=test\",\"type\": \"ssh\",\"usage\":\"login\",\"validityPeriod\":7300,\"account\":\"1234\"}"

SSHKEY="ssh-rsa ..."

http_status=$(curl -k \
    -u <user>:<password>\
    -X POST "xyz" \
    -H "Accept: application/json" \
    -H "Content-Type: multipart/mixed" \
    -F "datapart=$POSTDATA;type=application/json" \
    -F "certipart=$SSHKEY2;type=application/octet-stream" )

echo "https status $http_status \n"

Above curl command works fine (within a bash script).

With the following code I always get an exception. This code gets called from an Angular Frontend and has the ssh-rsa-Key as body.

@PostMapping(value = "/v1/authentication/saveNewKey", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Certificate saveNewKey(@RequestBody String newKey) throws JsonProcessingException {

        Certificate c = new Certificate();
        c.setSubject("CN=test");
        c.setType("ssh");
        c.setUsage("login");
        c.setValidityPeriod(7300);
        c.setAccount("1234");

        ObjectMapper mapper = new ObjectMapper();
        MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();

        bodyBuilder.part("datapart", mapper.writeValueAsString(c), MediaType.APPLICATION_JSON);
        bodyBuilder.part("certipart", newKey, MediaType.APPLICATION_OCTET_STREAM);

        Mono<Certificate> response = webClientBuilder.build()
                .post()
                .uri(apiBaseUrl   CERTIFICATES_API_URL)
                .contentType(MediaType.MULTIPART_MIXED)
                .body(BodyInserters.fromMultipartData(bodyBuilder.build()))
                .headers(headers -> {
                    headers.setBasicAuth(basicAuthUser, basicAuthPwd);
                    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
                    headers.setContentType(MediaType.MULTIPART_MIXED);
                })
                .retrieve()
                .bodyToMono(Certificate.class)
                .log();

        return response.block();
}
org.springframework.web.reactive.function.client.WebClientResponseException$UnsupportedMediaType: 415 Unsupported Media Type from POST xyz
        at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:212)
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
        *__checkpoint ? 415 from POST xyz [DefaultWebClient]
Original Stack Trace:
                at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:212)
...

What am I missing?

CodePudding user response:

I was able to solve my problem.

If adding the body with BodyInserters.fromMultipartData, then the ContentType will always be multipart/form-data. This ContentType is not allowed on my API.

.body(BodyInserters.fromMultipartData(bodyBuilder.build()))

Solution: Build the body outside of the webClientbuilder

MultiValueMap<String, HttpEntity<?>> body = bodyBuilder.build();

and add this body to the bodyValue (not .body()!)

.bodyValue(body)

This will result in a ContentType of multipart/mixed (if correctly set like in my question).

  • Related