Рубрики
Без рубрики

Ведение журнала Вызовов веб-клиента Spring

Узнайте, как регистрировать вызовы веб-клиента Spring, полезные для аудита и отладки.

Автор оригинала: baeldung.

1. Обзор

В этом уроке мы покажем, как настроить веб – клиент Spring – реактивный HTTP-клиент-для регистрации запросов и ответов.

2. Веб-клиент

Веб-клиент – это реактивный и неблокирующий интерфейс для HTTP-запросов, основанный на Spring Web Flux . Он имеет функциональный, свободный API с реактивными типами для декларативной композиции.

За кулисами Веб-клиент вызывает HTTP-клиент. Реактор Netty по умолчанию и реактивный HttpClient пристани также поддерживается. Кроме того, можно подключить другие реализации HTTP-клиента, настроив Клиентский соединитель для WebClient .

3. Регистрация запросов и ответов

Значение по умолчанию HttpClient используется WebClient является реализацией Netty, поэтому после того, как мы изменим реактор.netty.http.client уровень ведения журнала для ОТЛАДКИ, мы можем видеть некоторые записи запросов, но если нам нужен настроенный журнал, мы можем настроить e наши регистраторы с помощью WebClient#filters :

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

В этом фрагменте кода мы добавили два отдельных фильтра для регистрации запроса и ответа.

Давайте реализуем запрос журнала с помощью Функции фильтра обмена#обработчика запросов :

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);
    });
}

ответ журнала тот же, но вместо этого мы должны использовать Функцию фильтра обмена#процессора ответов .

Теперь мы можем изменить реактор.netty.http.client log level to INFO или ERROR для более чистого вывода.

4. Протоколирование запроса и ответа с телом

HTTP-клиенты имеют функции для регистрации тел запросов и ответов. Таким образом, для достижения этой цели мы собираемся использовать HTTP-клиент с поддержкой журнала с нашим WebClient.

Мы можем сделать это, вручную установив WebClient.Builder# clientConnector – давайте посмотрим с HTTP-клиентами Jetty и Netty.

4.1. Ведение журнала с помощью Jetty HttpClient

Во-первых, давайте добавим зависимость Maven для jetty-reactive-httpclient в наш pom:


    org.eclipse.jetty
    jetty-reactive-httpclient
    1.1.6

Затем мы создадим индивидуальный причал 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

Во-первых, давайте создадим Нетти HttpClient :

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

Включив прослушку, каждый запрос и ответ будут регистрироваться в полном объеме.

Затем мы должны установить уровень журнала клиентского пакета Netty reactor.netty.http.client to DEBUG :

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

Теперь давайте построим Веб-клиент :

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

Наш WebClient будет регистрировать каждый запрос и ответ в полном объеме, но формат по умолчанию встроенного регистратора Netty содержит как шестнадцатеричное, так и текстовое представление тел , а также множество данных о событиях запроса и ответа.

Итак, если нам нужен только текстовый регистратор для Netty, мы можем настроить HttpClient :

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

5. Заключение

В этом уроке мы использовали несколько методов регистрации данных запросов и ответов при использовании Spring Web Client .

Как всегда, код доступен на GitHub .