[英]WebClient Request and Response body logging
我正在尝试根据发出 WebClient 调用时收到的请求和响应数据制作 POJO。 但是我没有以字符串/JSON 可读形式获取请求正文,而是获取了 BodyInsertor。 我正在使用 Exchange 过滤器。
public ExchangeFilterFunction logWebRequest() {
return (request, next) -> {
log.info("Entered in logWebRequest for WebClient");
long startTime = System.currentTimeMillis();
Mono<ClientResponse> response = next.exchange(request);
long processingTimeInMs = System.currentTimeMillis() - startTime;
// request.body() -> Gives Body Insertor
WebRequestLog webRequestLog = webRequestService.makeWebRequestLog(request, response.block());
webRequestLog.setProcessingTimeInMs(processingTimeInMs);
log.info("WebRequest to be produced to kafka topic: " + webRequestLog);
kafkaService.produceAuditLog(webRequestLog);
return response;
};
}
我关注了一些文章,例如https://andrew-flower.com/blog/webclient-body-logging和https://www.gitmemory.com/issue/spring-projects/spring-framework/24262/570245788但没有任何效果为了我。
我的最终目标是用他们的身体捕捉请求和响应,并生成为 Kafka 收集的数据。
您可以通过对请求和响应的小操作来跟踪请求和响应有效负载:
public class TracingExchangeFilterFunction implements ExchangeFilterFunction {
return next.exchange(buildTraceableRequest(request))
.flatMap(response ->
response.body(BodyExtractors.toDataBuffers())
.next()
.doOnNext(dataBuffer -> traceResponse(response, dataBuffer))
.thenReturn(response)) ;
}
private ClientRequest buildTraceableRequest(
final ClientRequest clientRequest) {
return ClientRequest.from(clientRequest).body(
new BodyInserter<>() {
@Override
public Mono<Void> insert(
final ClientHttpRequest outputMessage,
final Context context) {
return clientRequest.body().insert(
new ClientHttpRequestDecorator(outputMessage) {
@Override
public Mono<Void> writeWith(final Publisher<? extends DataBuffer> body) {
return super.writeWith(
from(body).doOnNext(buffer ->
traceRequest(clientRequest, buffer)));
}
}, context);
}
}).build();
}
private void traceRequest(ClientRequest clientRequest, DataBuffer buffer) {
final ByteBuf byteBuf = NettyDataBufferFactory.toByteBuf(buffer);
final byte[] bytes = ByteBufUtil.getBytes(byteBuf);
// do some tracing e.g. new String(bytes)
}
private void traceResponse(ClientResponse response, DataBuffer dataBuffer) {
final byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
// do some tracing e.g. new String(bytes)
}
}
要添加到 Vicky Ajmera ,获取和记录请求的最佳方法是使用 ExchangeFilterFunction。
private ExchangeFilterFunction logRequest() {
return (clientRequest, next) -> {
logger.info("Request: {} {} {}", clientRequest.method(), clientRequest.url(), clientRequest.body());
clientRequest.headers()
.forEach((name, values) -> values.forEach(value -> logger.info("{}={}", name, value)));
return next.exchange(clientRequest);
};
}
但是要记录响应正文,您必须将 go 到 ClientHttpResponse 的较低级别,然后允许您拦截正文。 首先像这样扩展 ClientHttpResponseDecorator:
public class LoggingClientHttpResponse extends ClientHttpResponseDecorator {
private static final Logger logger = LoggerFactory.getLogger(LoggingClientHttpResponse.class);
private static final DataBufferFactory bufferFactory = new DefaultDataBufferFactory();
private final DataBuffer buffer = bufferFactory.allocateBuffer();
public LoggingClientHttpResponse(ClientHttpResponse delegate) {
super(delegate);
}
@Override
public Flux<DataBuffer> getBody() {
return super.getBody()
.doOnNext(this.buffer::write)
.doOnComplete(() -> logger.info("Response Body: {}", buffer.toString(StandardCharsets.UTF_8)));
}
}
然后像这样创建 ClientHttpConnector 的实现:
public class LoggingClientHttpConnector implements ClientHttpConnector {
private final ClientHttpConnector delegate;
public LoggingClientHttpConnector(ClientHttpConnector delegate) {
this.delegate = delegate;
}
@Override
public Mono<ClientHttpResponse> connect(HttpMethod method, URI uri, Function<? super ClientHttpRequest, Mono<Void>> requestCallback) {
return this.delegate.connect(method, uri, requestCallback).map(LoggingClientHttpResponse::new);
}
}
最后在构建 WebClient 时添加一个连接器:
HttpClient httpClient = HttpClient.create();
ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
WebClient.builder()
.baseUrl("http://localhost:8080")
.clientConnector(new LoggingClientHttpConnectorDecorator(connector))
.filter(logRequest())
.build();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.