336 단어
2 분
WebClient 쿼리 파라미터 Encoding
쿼리 파라미터 중복 인코딩
@Test
@DisplayName("지수 데이터 연동")
void syncData() throws InterruptedException {
String url = "https://apis.data.go.kr/1160100/service";
WebClient webClient = WebClient.builder()
.baseUrl(url)
.build();
webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/GetMarketIndexInfoService/getStockMarketIndex")
.queryParam("serviceKey",
"B2PGvTG0wqmd0e1LCOLzjljX%2BL9%2FnaGdzqbcfCpTnh1WnNfh2sWCo9ndw9ajnenHOx4prwnCGvivvRrixXR2pQ%3D%3D")
.queryParam("resultType", "json")
.queryParam("basDt", "20240731")
.build())
.retrieve()
.bodyToMono(String.class)
.subscribe(i -> {
System.out.println("i = " + i);
latch.countDown();
});
latch.await();
}<cmmMsgHeader>
<errMsg>SERVICE ERROR</errMsg>
<returnAuthMsg>SERVICE_KEY_IS_NOT_REGISTERED_ERROR</returnAuthMsg>
<returnReasonCode>30</returnReasonCode>
</cmmMsgHeader>
</OpenAPI_ServiceResponse>외부 API를 호출해서 쓰는 프로젝트를 진행하는 와중에 API가 정상적으로 호출 되는지 확인하기 위해 테스트 코드를 작성했었다.
그런데 .queryParam("serviceKey", "발급 받은 API키") 에서 API키를 정상적으로 인식하지 못하고, SERVICE_KEY_IS_NOT_REGISTERED_ERROR 에러가 발생했다. 이게 왜 이러나 구글에 열심히 검색해본 결과 WebClinet에는 기본적으로 queryParam을 받을 때 인코딩해서 들어간다고 한다.
해결 방법
DefaultUriBuilderFactory dubf = new DefaultUriBuilderFactory(url);
dubf.setEncodingMode(EncodingMode.VALUES_ONLY);
WebClient webClient = WebClient.builder()
.uriBuilderFactory(dubf)
.baseUrl(url)
.build();그냥 setEncodingMode(EncodingMode.VALUES_ONLY)를 통해 Encoding 못하게 막으면 된다.
번외
.retrieve()
.bodyToMono(String.class)참고로 WebClient에 retrieve()와 bodyToMono() 메서드가 있는 걸 확인할 수 있다.
retrieve()
Http Body를 가져온다. Http Status 코드가 4xx, 5xx인 경우 자동으로 예외를 발생 시켜준다. 그 외 에러 처리를 위해 onStatus() 메서드를 함께 사용할 수 있다.
bodyToMono()
Http 응답 body 내용을 Mono 타입으로 변환하는 것이다.
bodyToMono(String.class)의 경우 Mono<String>으로 변환된다.
WebClient 쿼리 파라미터 Encoding
https://realits.me/posts/webclientduplicateencoding/