Trying to log HTTP Request and Response using WebFilter based on the answer from here. However I'm unable to log request when request body is empty even after setting using switchIfEmpty.
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.channels.Channels;
@Component
@Slf4j
public class LoggingFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
var req = exchange.getRequest();
// var msg1 = new StringBuilder();
// msg1.append("REQ_IN");
// msg1.append("\n Address: ").append(req.getURI().toString());
// msg1.append("\n Content-Type: ").append(req.getHeaders().getContentType());
// msg1.append("\n HttpMethod: ").append(req.getMethod());
// msg1.append("\n ExchangeId: ").append(req.getId());
// msg1.append("\n headers: ").append(req.getHeaders());
// msg1.append("\n Payload: ");
// log.info(msg1.toString());
ServerHttpRequestDecorator loggingServerHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return super.getBody().doOnNext(dataBuffer -> {
var msg = new StringBuilder();
msg.append("REQ_IN");
msg.append("\n Address: ").append(super.getURI().toString());
msg.append("\n Content-Type: ").append(super.getHeaders().getContentType());
msg.append("\n HttpMethod: ").append(super.getMethod());
msg.append("\n ExchangeId: ").append(super.getId());
msg.append("\n headers: ").append(super.getHeaders());
msg.append("\n Payload: ");
try (FastByteArrayOutputStream bos = new FastByteArrayOutputStream()) {
Channels.newChannel(bos).write(dataBuffer.asByteBuffer().asReadOnlyBuffer());
var requestBody = IOUtils.toString(bos.toByteArray(), "UTF-8");
msg.append(requestBody);
} catch (IOException e) {
log.warn("Failed to read response message {}", e.getMessage());
}
log.info(msg.toString());
}).switchIfEmpty(v -> {
var msg = new StringBuilder();
msg.append("REQ_IN");
msg.append("\n Address: ").append(super.getURI().toString());
msg.append("\n Content-Type: ").append(super.getHeaders().getContentType());
msg.append("\n HttpMethod: ").append(super.getMethod());
msg.append("\n ExchangeId: ").append(super.getId());
msg.append("\n headers: ").append(super.getHeaders());
msg.append("\n Payload: ");
log.info(msg.toString());
});
}
};
ServerHttpResponseDecorator loggingServerHttpResponseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Mono<DataBuffer> buffer = Mono.from(body);
return super.writeWith(buffer.doOnNext(dataBuffer -> {
var msg = new StringBuilder();
msg.append("RES_OUT");
// msg.append("\n Address: ").append(super.getURI().toString());
msg.append("\n Content-Type: ").append(super.getHeaders().getContentType());
msg.append("\n ResponseCode: ").append(super.getRawStatusCode());
// msg.append("\n ExchangeId: ").append(super.get);
msg.append("\n headers: ").append(super.getHeaders());
msg.append("\n Payload: ");
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
Channels.newChannel(byteArrayOutputStream).write(dataBuffer.asByteBuffer().asReadOnlyBuffer());
var responseBody = IOUtils.toString(byteArrayOutputStream.toByteArray(), "UTF-8");
msg.append(responseBody);
} catch (Exception e) {
log.warn("Failed to read response message {}", e.getMessage());
}
log.info(msg.toString());
}));
}
};
return chain.filter(exchange.mutate().request(loggingServerHttpRequestDecorator).response(loggingServerHttpResponseDecorator).build());
}
}