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