public DinosaurNameDto getRecommendedDinosaurName(FileDto fileDto) {
MultipartBodyBuilder builder = new MultipartBodyBuilder();
// Add file part
Resource image = fileDto.getFile().getResource();
builder.part("file", image);
// Build and use
MultiValueMap<String, HttpEntity<?>> multipartBody = builder.build();
return webClient.post()
.uri("/v1/....")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.MULTIPART_FORM_DATA)
//.body(BodyInserters.fromMultipartData(multipartBody))
.bodyValue(multipartBody)
.retrieve()
.bodyToMono(xxx.class)
.onErrorResume(WebClientResponseException.class,
ex -> ex.getStatusCode().value() == 404 ? Mono.empty() : Mono.error(ex))
.block();
}
2023-04-03T00:23:51.998+09:00 ERROR 25196 --- [nio-8086-exec-2] c.s.d.a.e.GlobalExceptionHandler : handleGlobalException
org.springframework.web.reactive.function.client.WebClientResponseException$UnprocessableEntity: 422 Unprocessable Entity from POST http://............
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:329)
Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below:
Error has been observed at the following site(s):
*__checkpoint ⇢ 422 UNPROCESSABLE_ENTITY from POST http://.......... [DefaultWebClient]
Original Stack Trace:
at ............
Suppressed: java.lang.Exception: #block terminated with an error
at ............
422 Error code에 대해 검색을 해봤는데, FastAPI 환경에서 이 오류를 마주했다는 글을 보게 되었다. 그래서 그쪽으로 고민하기 시작했다.
그렇다면 어느 부분에서?
1) uri 부분 ❌
uri("/v1/....")
➡️ 꼼꼼히 봤는데 틀린 부분이 없었음.
2) accept 부분 ❌
.accept(MediaType.APPLICATION_JSON)
➡️ 사실 처음에 뭔지 모르고 막 쓰다가 accepct 부분에 MediaType.MULTIPART_FORM_DATA를 써놨었음. 근데 이건 문제가 없었음.
3) contentType 부분 ❌
.contentType(MediaType.MULTIPART_FORM_DATA)
➡️ 이건 틀릴 리가 없는데 내가 accept랑 반대로 썼나? 헷갈릴 정도로 도저히 틀린 부분을 못찾겠는 상태였음.....
4) body 부분 ❌
//.body(BodyInserters.fromMultipartData(multipartBody))
.bodyValue(multipartBody)
➡️ 원래 밑의 코드로 작성했었는데 하도 틀린 부분을 못찾겠어서 블로그 검색 코드로 바꿔봤음. 근데 역시나 이건 문제가 아님.
5) MultipartBodyBuilder 부분 ⭕
MultipartBodyBuilder builder = new MultipartBodyBuilder();
// Add file part
Resource image = fileDto.getFile().getResource();
builder.part("file", image);
// Build and use
MultiValueMap<String, HttpEntity<?>> multipartBody = builder.build();
➡️ 이것도 원래 이 코드였는데 하도 안 돼서 블로그 검색 코드(byte 배열 이용하고 header 설정해주고 하는,,)로 바꿔봤으나.... 똑같았다.
근데 !! 생각해보니 Server 쪽에선 "file"이 아니라 "image"로 받고 있던 거였음 ㅜㅜ
Resource image = fileDto.getFile().getResource();
builder.part("file", image);
⬇️
Resource image = fileDto.getFile().getResource();
builder.part("image", image);
공식 API Reference (RestDoc)만 보고 그대로 따라해도 문제 없는 게 맞았음.
그냥 Server 쪽의 request parameter 이름이 일치하지 않는 단순 실수인데 엄한 데에서 원인을 찾으려고 했다