1. 개요

이 튜토리얼에서는 요청과 응답을 기록하기 위해 반응 형 HTTP 클라이언트 인 Spring의 WebClient 를 사용자 정의하는 방법을 보여줄 것 입니다.

2. WebClient

WebClientSpring WebFlux를 기반으로하는 HTTP 요청을위한 반응적이고 비 차단적인 인터페이스입니다 . 선언적 구성을위한 반응 유형이있는 기능적이고 유창한 API가 있습니다.

뒤에서 WebClient 는 HTTP 클라이언트를 호출합니다. Reactor Netty가 기본이며 Jetty의 반응 적 HttpClient 도 지원됩니다. 또한 WebClientClientConnector설정하여 HTTP 클라이언트의 다른 구현을 연결할 수 있습니다 .

3. 요청 및 응답 로깅

기본 HttpClient를 가 사용하는 웹 클라이언트 , 그래서 그물코 구현되고 우리가 변경 한 후 reactor.netty.http.client 에 대한 로깅 수준을 DEBUG를, 우리가 어떤 요청 로깅을 볼 수 있지만 우리는 사용자 정의 로그를 필요로하는 경우, 우리가 할 수 configur 전자 우리의 로거를 통해 WebClient # filters :

WebClient
  .builder()
  .filters(exchangeFilterFunctions -> {
      exchangeFilterFunctions.add(logRequest());
      exchangeFilterFunctions.add(logResponse());
  })
  .build()

이 코드 스 니펫에서는 요청과 응답을 기록하기 위해 두 개의 개별 필터를 추가했습니다.

ExchangeFilterFunction # ofRequestProcessor 를 사용하여 logRequest구현해 보겠습니다 .

ExchangeFilterFunction logRequest() {
    return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
        if (log.isDebugEnabled()) {
            StringBuilder sb = new StringBuilder("Request: \n");
            //append clientRequest method and url
            clientRequest
              .headers()
              .forEach((name, values) -> values.forEach(value -> /* append header key/value */));
            log.debug(sb.toString());
        }
        return Mono.just(clientRequest);
    });
}

logResponse 는 동일 하지만 대신 ExchangeFilterFunction # ofResponseProcessor 를 사용해야 합니다.

이제 reactor.netty.http.client 로그 수준을 INFO 또는 ERROR변경하여 더 깨끗한 출력을 얻을 수 있습니다.

4. Body로 요청 및 응답 로깅

HTTP 클라이언트에는 요청 및 Response body을 기록하는 기능이 있습니다. 따라서 목표를 달성하기 위해 WebClient 와 함께 로그 지원 HTTP 클라이언트를 사용할 것 입니다.

WebClient.Builder # clientConnector  를 수동으로 설정하여이를 수행 할 수 있습니다. Jetty 및 Netty HTTP 클라이언트를 살펴 보겠습니다.

4.1. Jetty HttpClient로 로깅

먼저 jetty-reactive-httpclient대한 Maven 의존성을 pom에 추가해 보겠습니다 .

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-reactive-httpclient</artifactId>
    <version>1.0.3</version>
</dependency>

그런 다음 맞춤형 Jetty HttpClient 를 생성합니다 .

SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
HttpClient httpClient = new HttpClient(sslContextFactory) {
    @Override
    public Request newRequest(URI uri) {
        Request request = super.newRequest(uri);
        return enhance(request);
    }
};

여기에서 HttpClient # newRequest를 재정의 한 다음 요청 을 로그 향상 기에 래핑했습니다 .

다음으로 요청의 각 부분을 사용할 수있을 때 기록 할 수 있도록 요청에 이벤트를 등록해야합니다.

Request enhance(Request request) {
    StringBuilder group = new StringBuilder();
    request.onRequestBegin(theRequest -> {
        // append request url and method to group
    });
    request.onRequestHeaders(theRequest -> {
        for (HttpField header : theRequest.getHeaders()) {
            // append request headers to group
        }
    });
    request.onRequestContent((theRequest, content) -> {
        // append content to group
    });
    request.onRequestSuccess(theRequest -> {
        log.debug(group.toString());
        group.delete(0, group.length());
    });
    group.append("\n");
    request.onResponseBegin(theResponse -> {
        // append response status to group
    });
    request.onResponseHeaders(theResponse -> {
        for (HttpField header : theResponse.getHeaders()) {
            // append response headers to group
        }
    });
    request.onResponseContent((theResponse, content) -> {
        // append content to group
    });
    request.onResponseSuccess(theResponse -> {
        log.debug(group.toString());
    });
    return request;
}

마지막으로 WebClient 인스턴스 를 빌드해야 합니다.

WebClient
  .builder()
  .clientConnector(new JettyClientHttpConnector(httpClient))
  .build()

물론 이전처럼 RequestLogEnhancer 의 로그 수준 DEBUG 로 설정해야합니다  .

4.2. Netty HttpClient로 로깅

먼저 Netty HttpClient를 만들어 보겠습니다 .

HttpClient httpClient = HttpClient
  .create()
  .wiretap(true)

도청을 활성화하면 각 요청과 응답이 자세히 기록됩니다.

다음으로 Netty의 클라이언트 패키지 reactor.netty.http.client 의 로그 수준 DEBUG 로 설정해야합니다 .

logging.level.reactor.netty.http.client=DEBUG

이제 WebClient를 빌드 해 보겠습니다 .

WebClient
  .builder()
  .clientConnector(new ReactorClientHttpConnector(httpClient))
  .build()

우리의 웹 클라이언트는 전체 세부의 모든 요청 및 응답을 기록합니다, 하지만 인 Netty의 기본 형식은 내장 로거 진수 및 텍스트 몸의 표현이 모두 포함되어 있으며 요청 및 응답 이벤트에 대한 많은 데이터를.

따라서 Netty 용 텍스트 로거 만 필요하면 HttpClient를 구성 할 수 있습니다 .

HttpClient httpClient = HttpClient
  .create()
  .wiretap("reactor.netty.http.client.HttpClient", 
    LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL);

5. 결론

이 튜토리얼에서 우리는 Spring WebClient 를 사용하는 동안 요청 및 응답 데이터를 로깅하기 위해 여러 기술을 사용했습니다 .

항상 그렇듯이 코드는 GitHub에서 사용할 수 있습니다 .