[英]Copy of the request/response body on a Spring reactive app?
I'm looking into optimal ways of accessing the HTTP request and response bodies for tracing in a Spring reactive application.我正在研究访问 HTTP 请求和响应主体以在 Spring 反应式应用程序中进行跟踪的最佳方法。
For previous versions, we've leveraged Servlet filters and Servlet request wrappers to consume the incoming request's input stream and hold a copy of it for asynchronous processing of the traces (we send them to Elasticsearch).对于以前的版本,我们利用 Servlet 过滤器和 Servlet 请求包装器来使用传入请求的输入流并保存它的副本以异步处理跟踪(我们将它们发送到 Elasticsearch)。
But for a Spring reactive app (using webflux), I'm wondering what'd be the most appropriate way to access the requests before they're decoded.但是对于 Spring 反应式应用程序(使用 webflux),我想知道在解码请求之前访问请求的最合适方法是什么。 Any thoughts?
有什么想法吗?
Turns out this can be achieved using the provided decorators : ServerWebExchangeDecorator
, ServerHttpRequestDecorator
and ServerHttpResponseDecorator
, respectively.事实证明,这可以使用提供的装饰器来实现:分别是
ServerWebExchangeDecorator
、 ServerHttpRequestDecorator
和ServerHttpResponseDecorator
。
Here's a sample request decorator that accumulates the DataBuffer
contents as its read by the request's default subscriber:这是一个示例请求装饰器,它累积
DataBuffer
内容作为请求的默认订阅者读取的内容:
@Slf4j
public class CachingServerHttpRequestDecorator extends ServerHttpRequestDecorator {
@Getter
private final OffsetDateTime timestamp = OffsetDateTime.now();
private final StringBuilder cachedBody = new StringBuilder();
CachingServerHttpRequestDecorator(ServerHttpRequest delegate) {
super(delegate);
}
@Override
public Flux<DataBuffer> getBody() {
return super.getBody().doOnNext(this::cache);
}
@SneakyThrows
private void cache(DataBuffer buffer) {
cachedBody.append(UTF_8.decode(buffer.asByteBuffer())
.toString());
}
public String getCachedBody() {
return cachedBody.toString();
}
Just make sure that, when you decorate the ServerWebExchange
passed by the WebFilter
, you also override getRequest()
to return the request decorator as well:只要确保,当您装饰
ServerWebExchange
由通过WebFilter
,你也重写getRequest()
返回请求装饰,以及:
public final class PartnerServerWebExchangeDecorator extends ServerWebExchangeDecorator {
private final ServerHttpRequestDecorator requestDecorator;
private final ServerHttpResponseDecorator responseDecorator;
public PartnerServerWebExchangeDecorator(ServerWebExchange delegate) {
super(delegate);
this.requestDecorator = new PartnerServerHttpRequestDecorator(delegate.getRequest());
this.responseDecorator = new PartnerServerHttpResponseDecorator(delegate.getResponse());
}
@Override
public ServerHttpRequest getRequest() {
return requestDecorator;
}
@Override
public ServerHttpResponse getResponse() {
return responseDecorator;
}
}
On the filter:在过滤器上:
@Component
public class TracingFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(new PartnerServerWebExchangeDecorator(exchange));
}
}
Which can be used as such (beware the statically imported functions):可以这样使用(注意静态导入的函数):
@Bean
public HttpHandler myRoute(MyHandler handler) {
final RouterFunction<ServerResponse> routerFunction =
route(POST("/myResource"), handler::persistNotification);
return webHandler(toWebHandler(routerFunction))
.filter(new TracingFilter())
.build();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.