feat: WebClient module 확장 적용
parent
98764f06eb
commit
1b55a58e39
@ -0,0 +1,138 @@
|
||||
package kr.xit.core.spring.config.support;
|
||||
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||
import io.netty.handler.timeout.WriteTimeoutHandler;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.http.codec.LoggingCodecSupport;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.util.DefaultUriBuilderFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.netty.resources.ConnectionProvider;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description : WebClient configuration
|
||||
*
|
||||
* packageName : kr.xit.core.spring.config.support
|
||||
* fileName : WebClientConfig
|
||||
* author : julim
|
||||
* date : 2023-09-06
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-09-06 julim 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class WebClientConfig {
|
||||
|
||||
@Value("${contract.connection.timeout:5000}")
|
||||
private int connectTimeout;
|
||||
@Value("${contract.connection.readTimeout:5000}")
|
||||
private int readTimeout;
|
||||
|
||||
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
|
||||
|
||||
// HttpClient 총 연결 시간
|
||||
HttpClient httpClient = HttpClient.create()
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout)
|
||||
.responseTimeout(Duration.ofMillis(this.connectTimeout))
|
||||
.doOnConnected(conn ->
|
||||
conn.addHandlerLast(new ReadTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS))
|
||||
.addHandlerLast(new WriteTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS)));
|
||||
|
||||
|
||||
/**
|
||||
* setEncodingMode : GET 요청의 파라미터 셋팅을 하기 위한 URI 템플릿의 인코딩을 위한 설정
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public WebClient webClient() {
|
||||
// 256KB 보다 큰 HTTP 메시지를 처리 시도 → DataBufferLimitException 에러 발생 방어
|
||||
ExchangeStrategies es = ExchangeStrategies.builder()
|
||||
.codecs(configurer -> {
|
||||
configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024);
|
||||
//configurer.customCodecs().register(new Jackson2JsonDecoder());
|
||||
//configurer.customCodecs().register(new Jackson2JsonEncoder());
|
||||
})
|
||||
.build();
|
||||
|
||||
//FIXME::rest call async 로깅
|
||||
// ExchangeStrategies를 통해 setEnableLoggingRequestDetails(true)로 설정
|
||||
// boot에서 로깅 org.springframework.web.reactive.function.client.ExchangeFunctions: DEBUG 하여 활성
|
||||
es.messageWriters()
|
||||
.stream()
|
||||
.filter(LoggingCodecSupport .class::isInstance)
|
||||
.forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));
|
||||
|
||||
|
||||
|
||||
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
|
||||
return WebClient.builder()
|
||||
.uriBuilderFactory(factory)
|
||||
.clientConnector(new ReactorClientHttpConnector(httpClient))
|
||||
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024))
|
||||
.exchangeStrategies(es)
|
||||
.filters(exchangeFilterFunctions -> {
|
||||
exchangeFilterFunctions.add(logRequest());
|
||||
exchangeFilterFunctions.add(logResponse());
|
||||
//TODO::에러발생시 점검필요
|
||||
//exchangeFilterFunctions.add(errorHandler());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* maxConnections : connection pool의 갯수
|
||||
* pendingAcquireTimeout : 커넥션 풀에서 커넥션을 얻기 위해 기다리는 최대 시간
|
||||
* pendingAcquireMaxCount : 커넥션 풀에서 커넥션을 가져오는 시도 횟수 (-1: no limit)
|
||||
* maxIdleTime : 커넥션 풀에서 idle 상태의 커넥션을 유지하는 시간
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public ConnectionProvider connectionProvider() {
|
||||
return ConnectionProvider.builder("http-pool")
|
||||
.maxConnections(100)
|
||||
.pendingAcquireTimeout(Duration.ofMillis(0))
|
||||
.pendingAcquireMaxCount(-1)
|
||||
.maxIdleTime(Duration.ofMillis(1000L))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
private ExchangeFilterFunction logRequest() {
|
||||
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
|
||||
if (log.isDebugEnabled()) {
|
||||
StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Request <<<<<<<<<<<<<\n");
|
||||
clientRequest
|
||||
.headers()
|
||||
.forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n")));
|
||||
log.debug(sb.toString());
|
||||
}
|
||||
return Mono.just(clientRequest);
|
||||
});
|
||||
}
|
||||
|
||||
private ExchangeFilterFunction logResponse() {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||
StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Response <<<<<<<<<<<<<\n");
|
||||
clientResponse.headers()
|
||||
.asHttpHeaders()
|
||||
.forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n")));
|
||||
log.debug(sb.toString());
|
||||
return Mono.just(clientResponse);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,262 +0,0 @@
|
||||
package kr.xit.core.spring.util;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.http.codec.LoggingCodecSupport;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.reactive.function.client.WebClientRequestException;
|
||||
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.ConnectTimeoutException;
|
||||
import io.netty.handler.timeout.ReadTimeoutException;
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||
import io.netty.handler.timeout.WriteTimeoutHandler;
|
||||
import kr.xit.core.consts.Constants;
|
||||
import kr.xit.core.exception.BizRuntimeException;
|
||||
import kr.xit.core.model.ApiResponseDTO;
|
||||
import kr.xit.core.model.ErrorDTO;
|
||||
import kr.xit.core.spring.util.error.ClientError;
|
||||
import kr.xit.core.spring.util.error.ErrorParse;
|
||||
import kr.xit.core.spring.util.error.ServerError;
|
||||
import kr.xit.core.support.utils.Checks;
|
||||
import kr.xit.core.support.utils.JsonUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description : react Restfull Util
|
||||
*
|
||||
* packageName : kr.xit.core.spring.util
|
||||
* fileName : ApiWebClient
|
||||
* author : julim
|
||||
* date : 2023-04-28
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-04-28 julim 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
* @see kr.xit.core.spring.config.AsyncExecutorConfig
|
||||
* @see ClientError
|
||||
* @see ServerError
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ApiWebClient {
|
||||
private final WebClient webClient;
|
||||
|
||||
|
||||
public ApiWebClient(
|
||||
@Value("${contract.provider.kakao.token:}")
|
||||
String accessToken,
|
||||
@Value("${contract.provider.kakao.uuid:}")
|
||||
String contractUuid,
|
||||
@Value("${contract.provider.connection.timeout:5000}")
|
||||
int connectionTimeout,
|
||||
@Value("${contract.provider.connection.readTimeout:5000}")
|
||||
int readTimeout
|
||||
) {
|
||||
ExchangeStrategies es = ExchangeStrategies.builder()
|
||||
.codecs(configurer -> {
|
||||
configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024);
|
||||
//configurer.customCodecs().register(new Jackson2JsonDecoder());
|
||||
//configurer.customCodecs().register(new Jackson2JsonEncoder());
|
||||
})
|
||||
.build();
|
||||
|
||||
//FIXME::rest call async 로깅
|
||||
// ExchangeStrategies를 통해 setEnableLoggingRequestDetails(true)로 설정
|
||||
// boot에서 로깅 org.springframework.web.reactive.function.client.ExchangeFunctions: DEBUG 하여 활성
|
||||
es.messageWriters()
|
||||
.stream()
|
||||
.filter(LoggingCodecSupport.class::isInstance)
|
||||
.forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));
|
||||
|
||||
|
||||
this.webClient = WebClient.builder()
|
||||
.clientConnector(httpClient(connectionTimeout, readTimeout))
|
||||
.baseUrl("http://localhost:8081") // (1) 외부 API Base URl
|
||||
.defaultHeaders((headers)->{
|
||||
headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Constants.CHARSET_UTF8));
|
||||
headers.set(Constants.HeaderName.TOKEN.getCode(), String.format("%s %s", Constants.JwtToken.GRANT_TYPE.getCode(), accessToken));
|
||||
headers.set(Constants.HeaderName.UUID.getCode(), contractUuid);
|
||||
|
||||
})
|
||||
.exchangeStrategies(es)
|
||||
.filters(exchangeFilterFunctions -> {
|
||||
exchangeFilterFunctions.add(logRequest());
|
||||
exchangeFilterFunctions.add(logResponse());
|
||||
//TODO::에러발생시 점검필요
|
||||
//exchangeFilterFunctions.add(errorHandler());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
//TODO:: ApiResponseDTO로 return 하도록 해야할 듯
|
||||
// CompletableFuture.supplyAsync().handle() / exceptionally() 사용을 위해
|
||||
/**
|
||||
* <pre>
|
||||
* Async call - Response Entity(상태정보등) 가 필요한 경우
|
||||
* @param url call url
|
||||
* @param method POST|GET
|
||||
* @param body JSON String type
|
||||
* @param rtnClzz rtnClzz return type class
|
||||
* (ex: new KkopayDocDTO.DocStatusResponse().getClass())
|
||||
* @return T rtnClzz return DTO
|
||||
* </pre>
|
||||
*/
|
||||
public <T> T exchange(String url, HttpMethod method, Object body, Class<T> rtnClzz) {
|
||||
|
||||
return webClient.method(method)
|
||||
.uri(url)
|
||||
.bodyValue(Objects.requireNonNullElse(body, ""))
|
||||
.exchangeToMono(res -> res.bodyToMono(rtnClzz))
|
||||
.block();
|
||||
}
|
||||
|
||||
public <T> T exchange2(String url, HttpMethod method, Object body, Class<T> rtnClzz) {
|
||||
|
||||
return webClient.method(method)
|
||||
.uri(url)
|
||||
|
||||
.bodyValue(Objects.requireNonNullElse(body, ""))
|
||||
.exchangeToMono(res -> res.bodyToMono(rtnClzz))
|
||||
|
||||
.block();
|
||||
}
|
||||
|
||||
public <T> ApiResponseDTO<T> sendError(Throwable e) {
|
||||
|
||||
Map<String,Object> map = ErrorParse.extractError(e.getCause());
|
||||
return ApiResponseDTO.error(String.valueOf(map.get("code")), String.valueOf(map.get("message")), (HttpStatus)map.get("httpStatus"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Async call - body 만 필요한 경우
|
||||
* @param url call url
|
||||
* @param method POST|GET
|
||||
* @param body JSON String type
|
||||
* @param rtnClzz rtnClzz return type class
|
||||
* (ex: new KkopayDocDTO.DocStatusResponse().getClass())
|
||||
* @return T rtnClzz return DTO
|
||||
* </pre>
|
||||
*/
|
||||
public <T> T retrive(String url, HttpMethod method, Object body, Class<T> rtnClzz) {
|
||||
|
||||
return webClient.mutate()
|
||||
.build()
|
||||
.method(method)
|
||||
.uri(url)
|
||||
.bodyValue(Objects.requireNonNullElse(body, ""))
|
||||
.retrieve()
|
||||
.onStatus(
|
||||
status -> status.is4xxClientError() || status.is5xxServerError(),
|
||||
res -> res.bodyToMono(String.class).map(BizRuntimeException::create))
|
||||
.bodyToMono(rtnClzz)
|
||||
.block();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private ReactorClientHttpConnector httpClient(int connectTimeout, int readTimeout){
|
||||
return new ReactorClientHttpConnector(
|
||||
HttpClient.create()
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout)
|
||||
.responseTimeout(Duration.ofMillis(connectTimeout))
|
||||
.doOnConnected(conn ->
|
||||
conn.addHandlerLast(new ReadTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS))
|
||||
.addHandlerLast(new WriteTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS)))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
ExchangeFilterFunction logRequest() {
|
||||
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
|
||||
if (log.isDebugEnabled()) {
|
||||
StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Request <<<<<<<<<<<<<\n");
|
||||
clientRequest
|
||||
.headers()
|
||||
.forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n")));
|
||||
log.debug(sb.toString());
|
||||
}
|
||||
return Mono.just(clientRequest);
|
||||
});
|
||||
}
|
||||
|
||||
ExchangeFilterFunction logResponse() {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||
StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Response <<<<<<<<<<<<<\n");
|
||||
clientResponse.headers()
|
||||
.asHttpHeaders()
|
||||
.forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n")));
|
||||
log.debug(sb.toString());
|
||||
return Mono.just(clientResponse);
|
||||
});
|
||||
}
|
||||
|
||||
ExchangeFilterFunction errorHandler() {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||
HttpStatus status = clientResponse.statusCode();
|
||||
|
||||
if (clientResponse.statusCode().is4xxClientError()) {
|
||||
return clientResponse.bodyToMono(String.class)
|
||||
.flatMap(errorBody -> Mono.error(new ClientError(status, errorBody)));
|
||||
|
||||
} else if (clientResponse.statusCode().is5xxServerError()) {
|
||||
return clientResponse.bodyToMono(String.class)
|
||||
.flatMap(errorBody -> Mono.error(new ServerError(status, errorBody)));
|
||||
|
||||
}
|
||||
return Mono.just(clientResponse);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public <T> T exchange3(String url, HttpMethod method, Object body, Class<T> rtnClzz) {
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
AtomicReference<T> result = new AtomicReference<>();
|
||||
|
||||
webClient.mutate()
|
||||
.build()
|
||||
.method(method)
|
||||
.uri(url)
|
||||
.bodyValue(body)
|
||||
.exchangeToMono(res -> res.bodyToMono(rtnClzz))
|
||||
.onErrorContinue((e, i) -> {
|
||||
log.error("{}", e);
|
||||
})
|
||||
.doOnTerminate(() -> cdl.countDown())
|
||||
.subscribe(data -> result.set(data));
|
||||
try {
|
||||
cdl.await();
|
||||
} catch (InterruptedException e) {
|
||||
// thread pool에 에러상태 set
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return result.get();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
package kr.xit.core.spring.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import kr.xit.core.consts.Constants;
|
||||
import kr.xit.core.exception.BizRuntimeException;
|
||||
import kr.xit.core.model.ApiResponseDTO;
|
||||
import kr.xit.core.spring.config.support.WebClientConfig;
|
||||
import kr.xit.core.spring.util.error.ClientError;
|
||||
import kr.xit.core.spring.util.error.ErrorParse;
|
||||
import kr.xit.core.spring.util.error.ServerError;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description : react Restfull Util
|
||||
*
|
||||
* packageName : kr.xit.core.spring.util
|
||||
* fileName : ApiWebClientUtil
|
||||
* author : julim
|
||||
* date : 2023-09-06
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-09-06 julim 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
* @see kr.xit.core.spring.config.AsyncExecutorConfig
|
||||
* @see ClientError
|
||||
* @see ServerError
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ApiWebClientUtil {
|
||||
@Value("${contract.kakao.token:}")
|
||||
private String kkoAccessToken;
|
||||
@Value("${contract.kakao.uuid:}")
|
||||
private String kkoContractUuid;
|
||||
|
||||
private final WebClientConfig webClientConfig;
|
||||
|
||||
public <T> T get(final String url, final Class<T> responseDtoClass, Map<String, String> headerMap) {
|
||||
return webClientConfig.webClient().method(HttpMethod.GET)
|
||||
.uri(url)
|
||||
.headers(httpHeaders -> getHeaders(httpHeaders, headerMap))
|
||||
.retrieve()
|
||||
.onStatus(
|
||||
status -> status.is4xxClientError() || status.is5xxServerError(),
|
||||
res -> res.bodyToMono(String.class).map(BizRuntimeException::create))
|
||||
.bodyToMono(responseDtoClass)
|
||||
.block();
|
||||
}
|
||||
|
||||
public <T, V> T post(final String url, final V requestDto, final Class<T> responseDtoClass, Map<String, String> headerMap) {
|
||||
return webClientConfig.webClient().method(HttpMethod.POST)
|
||||
.uri(url)
|
||||
.headers(httpHeaders -> getHeaders(httpHeaders, headerMap))
|
||||
.bodyValue(requestDto)
|
||||
.retrieve()
|
||||
.onStatus(
|
||||
status -> status.is4xxClientError() || status.is5xxServerError(),
|
||||
res -> res.bodyToMono(String.class).map(BizRuntimeException::create))
|
||||
.bodyToMono(responseDtoClass)
|
||||
.block();
|
||||
}
|
||||
|
||||
public <T> T exchangeKko(final String url, final HttpMethod method, final Object body, final Class<T> rtnClzz) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
map.put(HttpHeaders.AUTHORIZATION,
|
||||
String.format("%s %s", Constants.JwtToken.GRANT_TYPE.getCode(), kkoAccessToken));
|
||||
map.put(Constants.HeaderName.UUID.getCode(), kkoContractUuid);
|
||||
|
||||
return exchange(url, method, body, rtnClzz, map);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Async call - Response Entity(상태정보등) 가 필요한 경우
|
||||
* @param url call url
|
||||
* @param method POST|GET
|
||||
* @param body JSON String type
|
||||
* @param rtnClzz rtnClzz return type class
|
||||
* (ex: new KkopayDocDTO.DocStatusResponse().getClass())
|
||||
* @return T rtnClzz return DTO
|
||||
* </pre>
|
||||
*/
|
||||
public <T> T exchange(final String url, final HttpMethod method, final Object body, final Class<T> rtnClzz, final Map<String,String> headerMap) {
|
||||
|
||||
return webClientConfig.webClient()
|
||||
.method(method)
|
||||
.uri(url)
|
||||
.headers(httpHeaders -> getHeaders(httpHeaders, headerMap))
|
||||
.bodyValue(Objects.requireNonNullElse(body, ""))
|
||||
.exchangeToMono(res -> res.bodyToMono(rtnClzz))
|
||||
.block();
|
||||
}
|
||||
|
||||
public <T> ApiResponseDTO<T> sendError(final Throwable e) {
|
||||
|
||||
Map<String,Object> map = ErrorParse.extractError(e.getCause());
|
||||
return ApiResponseDTO.error(String.valueOf(map.get("code")), String.valueOf(map.get("message")), (HttpStatus)map.get("httpStatus"));
|
||||
}
|
||||
|
||||
private URI createUrl(final String endPoint, final String... value) {
|
||||
return UriComponentsBuilder.fromUriString(endPoint)
|
||||
.build(value);
|
||||
}
|
||||
|
||||
private HttpHeaders getHeaders(final HttpHeaders headers, final Map<String, String> map) {
|
||||
|
||||
for(Map.Entry<String, String> e : map.entrySet()){
|
||||
headers.add(e.getKey(), e.getValue());
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
ExchangeFilterFunction errorHandler() {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||
HttpStatus status = clientResponse.statusCode();
|
||||
|
||||
if (clientResponse.statusCode().is4xxClientError()) {
|
||||
return clientResponse.bodyToMono(String.class)
|
||||
.flatMap(errorBody -> Mono.error(new ClientError(status, errorBody)));
|
||||
|
||||
} else if (clientResponse.statusCode().is5xxServerError()) {
|
||||
return clientResponse.bodyToMono(String.class)
|
||||
.flatMap(errorBody -> Mono.error(new ServerError(status, errorBody)));
|
||||
|
||||
}
|
||||
return Mono.just(clientResponse);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue