[英]Intercept Http Request body in spring boot gateway
We are running a bunch of microservices which are guarded by a central gateway (org.springframework.cloud:spring-cloud-starter-gateway:2.1.0) that routes requests to the responsible microservice behind it.我们正在运行一组由中央网关(org.springframework.cloud:spring-cloud-starter-gateway:2.1.0)保护的微服务,该网关将请求路由到其背后的负责微服务。
We now want to add a service, that shall get the importent parts of each request as copy (like headers, request path, request body...) via a restful interface for tracking / statistic reasons.我们现在要添加一个服务,该服务将通过一个用于跟踪/统计原因的 RESTful 接口将每个请求的重要部分作为副本(如标头、请求路径、请求正文...)获取。 To have the code for this only at one place, we want to add it directly to the gateway service.
为了只在一个地方有这个代码,我们想将它直接添加到网关服务中。
Implementing WebFilter seems to be a good start for this, but I'm having problems with the request body which is Flux<DataBuffer>
.实现 WebFilter 似乎是一个好的开始,但我遇到了请求正文
Flux<DataBuffer>
的问题。
Subscribing to it causes an error: Only one connection receive subscriber allowed.
订阅它会导致错误:
Only one connection receive subscriber allowed.
, because it's a unicast which prohibits multiple receivers of the content. ,因为它是禁止内容的多个接收者的单播。
@Slf4j
@Configuration
public class InterceptConfig implements WebFilter {
private final StatisticServiceProperties properties;
@Autowired
public InterceptConfig(StatisticServiceProperties properties) {
this.properties = properties;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
log.debug("request intercepted. sending to statistic service : " + request.getURI().toString());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
request.getBody().subscribe(dataBuffer -> {
try {
byteArrayOutputStream.write(dataBuffer.asInputStream().readAllBytes());
} catch (IOException e) {
log.debug("couldn't extract body from request", e);
}
});
new StatisticServiceClient(
new RestTemplate(),
properties.getBaseUrl() + "/statistic"
).createStatistic(
new CreateStatisticRequest(
new Date(),
request.getURI(),
request.getHeaders(),
byteArrayOutputStream.toByteArray()
)
);
return chain.filter(exchange);
}
}
Is there a way to get the content of the request body without breaking the application?有没有办法在不破坏应用程序的情况下获取请求正文的内容?
Edit: 18.11.2019编辑:18.11.2019
I found a solution that solves this for me: https://github.com/spring-cloud/spring-cloud-gateway/issues/747#issuecomment-451805283我找到了一个为我解决这个问题的解决方案: https://github.com/spring-cloud/spring-cloud-gateway/issues/747#issuecomment-451805283
This is not tested code but try to create ConnectableFlux
from original flux.这不是经过测试的代码,而是尝试从原始通量创建
ConnectableFlux
。 That should allow multiple subscribers:这应该允许多个订阅者:
Flux<DataBuffer> connFlux = request.getBody().share();
Flux.from(connFlux).subscribe(dataBuffer -> {
try {
byteArrayOutputStream.write(dataBuffer.asInputStream().readAllBytes());
} catch (IOException e) {
log.debug("couldn't extract body from request", e);
}
});
Did you try standard spring interceptor approach?您是否尝试过标准的 spring 拦截器方法?
https://www.baeldung.com/spring-mvc-handlerinterceptor https://www.tutorialspoint.com/spring_boot/spring_boot_interceptor.htm https://www.baeldung.com/spring-mvc-handlerinterceptor https://www.tutorialspoint.com/spring_boot/spring_boot_interceptor.htm
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.