来自 POST 的 415 不支持的媒体类型
415 Unsupported Media Type from POST
我需要使用 Spring/Webclient 创建一个 POST 调用,它可以很好地与 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"
上面的 curl 命令工作正常(在 bash 脚本中)。
使用下面的代码我总是得到一个异常。此代码从 Angular 前端调用,主体为 ssh-rsa-Key。
@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)
...
我错过了什么?
我能够解决我的问题。
如果使用 BodyInserters.fromMultipartData 添加正文,则 ContentType 将始终为 multipart/form-data。我的 API.
不允许使用此 ContentType
.body(BodyInserters.fromMultipartData(bodyBuilder.build()))
解决方法:
在 webClientbuilder
之外构建主体
MultiValueMap<String, HttpEntity<?>> body = bodyBuilder.build();
并将此正文添加到 bodyValue(不是 .body()!)
.bodyValue(body)
这将导致 multipart/mixed 的 ContentType(如果像我的问题一样正确设置)。
我需要使用 Spring/Webclient 创建一个 POST 调用,它可以很好地与 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"
上面的 curl 命令工作正常(在 bash 脚本中)。
使用下面的代码我总是得到一个异常。此代码从 Angular 前端调用,主体为 ssh-rsa-Key。
@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)
...
我错过了什么?
我能够解决我的问题。
如果使用 BodyInserters.fromMultipartData 添加正文,则 ContentType 将始终为 multipart/form-data。我的 API.
不允许使用此 ContentType.body(BodyInserters.fromMultipartData(bodyBuilder.build()))
解决方法: 在 webClientbuilder
之外构建主体MultiValueMap<String, HttpEntity<?>> body = bodyBuilder.build();
并将此正文添加到 bodyValue(不是 .body()!)
.bodyValue(body)
这将导致 multipart/mixed 的 ContentType(如果像我的问题一样正确设置)。