在Spring Boot Gateway中拦截Http Request主体

时间:2019-11-15 13:44:52

标签: java rest spring-cloud spring-webflux

我们正在运行一堆微服务,这些微服务由中央网关(org.springframework.cloud:spring-cloud-starter-gateway:2.1.0)保护,该网关将请求路由到背后的负责的微服务。

我们现在要添加一个服务,该服务将通过一个宁静的接口将每个请求的重要部分作为副本(例如标头,请求路径,请求正文...)作为副本进行跟踪/统计。为了只在一个地方使用此代码,我们想将其直接添加到网关服务中。

实施WebFilter似乎是一个不错的开始,但是我在请求正文Flux<DataBuffer>上遇到了问题。

订阅它会导致错误:Only one connection receive subscriber allowed.,因为它是单播,禁止内容的多个接收者。

@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);
    }
}

是否可以在不破坏应用程序的情况下获取请求正文的内容?

编辑:2019年11月18日

我找到了一个可以为我解决此问题的解决方案: https://github.com/spring-cloud/spring-cloud-gateway/issues/747#issuecomment-451805283

1 个答案:

答案 0 :(得分:0)