0

How can I intercept WebFilter requests after they have been converted from DTO to JSON String?

Of course I could add a ExchangeFilterFunction, but the clientRequest.body() only shows my input object, not the converted json string:

WebClient.builder().defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).filter(logRequest()).build();

private ExchangeFilterFunction logRequest() {
    return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
        LOGGER.info(clientRequest.body()); //body is MyRequest.class
        return Mono.just(clientRequest);
    });
}

MyRequestDto dto;
client.post().uri(url).syncBody(dto).retrieve().bodyToMono(MyResponseDto.class).block();

So I'm looking for a way to intercept the outgoing requests after they have been converted from dto to json string.

And the other way around, intercept responses before they are converted to dto from json.

membersound
  • 81,582
  • 193
  • 585
  • 1,120

1 Answers1

2

Data is written as a String but rather as a bytes in DataBuffer by JacksonEncoder. One way to intercept request is to override JSON encoder, and access DataBuffer directly or interpret it as a String.

Consumer<ClientCodecConfigurer> consumer = configurer ->
        configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder() {
            @Override
            public Flux<DataBuffer> encode(Publisher<?> inputStream, DataBufferFactory bufferFactory, ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
                return super.encode(inputStream, bufferFactory, elementType, mimeType, hints)
                        .doOnNext(dataBuffer -> System.out.println(StandardCharsets.UTF_8.decode(dataBuffer.asByteBuffer()).toString()));
            }
        });

WebClient webClient = WebClient.builder()
        .exchangeStrategies(ExchangeStrategies.builder().codecs(consumer).build())
        .build();

If the purpose is just to log outgoing message body, see this question: how to log Spring 5 WebClient call

arap
  • 499
  • 2
  • 6
  • 1
    Regarding your linked answer: there is same problem: inside the `ExchangeFilterFunction` the body is already encoded as DTO, thus not accessible as native buffer. Could you add an example on how to also intercept the response buffer to write it down? – membersound Jul 12 '19 at 08:08
  • it is in the answer ;) it prints JSON as expected – arap Jul 12 '19 at 08:19
  • And for `Jaxb2XmlDecoder`? How can I there get the databuffer from `Publisher inputStream`? – membersound Jul 15 '19 at 08:21
  • You can turn Publisher into Mono/Flux (example is in org.springframework.http.codec.xml.XmlEventDecoder#decode), and then do the same. – arap Jul 15 '19 at 09:31
  • Excuse my, for the goal of my question your answer works as expected! The outgoing requests are logged as json/xml strings. The problem is more with intercepting the response properly. Maybe you could also have a look? https://stackoverflow.com/questions/57037543/how-to-intercept-http-response-traffic-in-spring-webclient – membersound Jul 15 '19 at 10:08