简体   繁体   English

您如何在 Spring Cloud Gateway (Webflux) POST 过滤器中读取响应正文

[英]How do you read response body in Spring Cloud Gateway (Webflux) POST filter

Spring Cloud Gateway documents a post filter phase like this: https://cloud.spring.io/spring-cloud-static/Greenwich.RELEASE/single/spring-cloud.html#_writing_custom_gatewayfilter_factories Spring Cloud Gateway 记录了这样的后过滤阶段: https : //cloud.spring.io/spring-cloud-static/Greenwich.RELEASE/single/spring-cloud.html#_writing_custom_gatewayfilter_factories

I've implemented a filter that has nothing in pre filter phase, but I would like to manipulate the response body in post filter phase before committing it to the client waiting the response to succeed.我已经实现了一个在过滤前阶段没有任何内容的过滤器,但我想在将其提交给等待响应成功的客户端之前,在过滤后阶段操作响应主体。

I've managed to successfully alter the response but I have found no solution to how actually read the original response from the successful proxied request.我已经成功地改变了响应,但我没有找到如何从成功的代理请求中实际读取原始响应的解决方案。 I think I have tried almost everything and I know it's probably not the best practice to read the body in the middle of webflux flow as it sort of defeats the whole purpose.我想我已经尝试了几乎所有方法,我知道在 webflux 流中间读取主体可能不是最佳实践,因为它有点违背了整个目的。 But it drives me nuts it's that hard to just read the data from the response.但它让我发疯,从响应中读取数据很难。

My filter looks like this:我的过滤器看起来像这样:

class PostFilter : AbstractGatewayFilterFactory<PostFilter.Config>(Config::class.java) {
    @Autowired
    private lateinit var tokenService: TokenService

    /* This is required when implementing AbstractGatewayFilterFactory.
     * With config we could pass filter configurations in application.yml route config
     * This can be used if it is needed to parametrise filter functionality
     */
    class Config

    override fun apply(config: Config?): GatewayFilter {
        return GatewayFilter { exchange: ServerWebExchange, chain: GatewayFilterChain ->

            chain.filter(exchange).then(Mono.defer {
                val response = exchange.response
                val bytes: ByteArray = "Some text".toByteArray(StandardCharsets.UTF_8)
                val buffer: DataBuffer = exchange.response.bufferFactory().wrap(bytes)
                response.headers.contentLength = bytes.size.toLong()

                // How do I get the original response?
                response.writeWith(Flux.just(buffer))
            })


        }
    }
}

I found this example: https://github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebClientWriteResponseFilter.java where I see ClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR);我找到了这个例子: https : //github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter /WebClientWriteResponseFilter.java我看到ClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR); but when I try it, it doesn't contain a ClientResponse object that could be used to fetch the body.但是当我尝试它时,它不包含可用于获取正文的ClientResponse对象。 Instead I get netty's HttpClientResponse object that has no way to get hold of the response body.相反,我得到了无法获取响应正文的 netty 的HttpClientResponse对象。

I've searched numerous stackoverflow topics covering problems that look a bit similar but none of them are actually the same.我搜索了许多 stackoverflow 主题,涵盖的问题看起来有点相似,但实际上没有一个是相同的。

I also tried this approach as in this https://github.com/spring-cloud/spring-cloud-gateway/issues/177#issuecomment-361411981 where you can use ServerHttpResponseDecorator to read the body.我也尝试过这种方法,如https://github.com/spring-cloud/spring-cloud-gateway/issues/177#issuecomment-361411981 ,您可以在其中使用ServerHttpResponseDecorator来读取正文。 However, it only reads the body if the writeWith() method is called.但是,它仅在writeWith()方法时才读取正文。 So if I want the original response, I would have to get the original response as a DataBuffer to write it again so the writeWith would be triggered.因此,如果我想要原始响应,则必须将原始响应作为DataBuffer才能再次写入,以便触发 writeWith。 But if I had is as DataBuffer I wouldn't need the whole ServerHttpResponseDecorator at all.但是如果我把它当作DataBuffer我就根本不需要整个ServerHttpResponseDecorator

So please, help me - I've banged my head against the wall and feel like giving up on this.所以请帮助我 - 我的头撞在墙上,想放弃这个。 I usually never give up, since I feel this should be even trivial to do because it's such a simple thing: "read the response body after proxied request".我通常从不放弃,因为我觉得这应该是微不足道的,因为这是一件很简单的事情:“在代理请求后读取响应正文”。

Any ideas?有任何想法吗?

One way to get the response in readable format is (adapted from NettyWriteResponseFilter: https://github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyWriteResponseFilter.java ) is to use Netty Connection:以可读格式获取响应的一种方法是(改编自 NettyWriteResponseFilter: https : //github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java /org/springframework/cloud/gateway/filter/NettyWriteResponseFilter.java ) 是使用 Netty 连接:

            val connection: Connection = exchange.getAttribute(CLIENT_RESPONSE_CONN_ATTR) ?: error("Connection not found")
            val factory: NettyDataBufferFactory = response.bufferFactory() as NettyDataBufferFactory
            val body = connection.inbound().receive().retain().map(factory::wrap).next()
            body.doOnSuccess {    
                val dest = ByteArray(it.readableByteCount())
                it.read(dest)
                val originalResponse = String(dest, StandardCharsets.UTF_8)
                println(originalResponse)
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Spring 云网关(Webflux)后过滤器中获取原始响应正文 - How to get Original response body in Spring cloud gateway (Webflux) Post filter Spring 云网关 - 如何修改后过滤器中的响应正文 - Spring Cloud Gateway - How To Modify Response Body In Post Filter Spring Cloud Gateway:修改后的响应体被截断 - Spring Cloud Gateway: Modified Response Body is Truncated 如何在将响应返回给调用者时注销对 Spring WebFlux WebClient 请求的失败响应的正文? - How do I log out the body of a failed response to a Spring WebFlux WebClient request while returning the response to the caller? Spring Cloud Gateway-尝试在Web过滤器中读取请求正文时请求被卡住 - Spring Cloud Gateway - request stuck when trying to read request body in web filter 如何在 Spring Gateway 中获取响应体 - How to get response body in Spring Gateway 如何在 Spring WebFlux 的响应体中流式传输二进制数据 - How to stream binary data in a response body in Spring WebFlux 在 Spring Cloud Gateway 过滤器中提取 WebClient GET 响应值 - Extract WebClient GET response values within a Spring Cloud Gateway filter 如何在Cloud Api Gateway的响应主体中添加一些数据 - How to add some data in body of response for Cloud Api Gateway 如何在 Zuul 后置过滤器中获取响应正文? - How to get response body in Zuul post filter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM