首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Spring Cloud Gateway (Webflux) POST过滤器中读取响应正文

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

Stack Overflow用户
提问于 2019-12-11 21:06:49
回答 1查看 3.7K关注 0票数 3

Spring Cloud Gateway记录了一个像这样的后期过滤阶段:https://cloud.spring.io/spring-cloud-static/Greenwich.RELEASE/single/spring-cloud.html#_writing_custom_gatewayfilter_factories

我已经实现了一个在过滤前阶段没有任何内容的过滤器,但我希望在将其提交给等待响应成功的客户端之前,在过滤后阶段操作响应体。

我已经成功地更改了响应,但是我还没有找到如何从成功的代理请求中实际读取原始响应的解决方案。我想我已经尝试了几乎所有的方法,我知道在webflux流中间阅读正文可能不是最好的做法,因为这有点违背了整个目的。但它让我抓狂,仅仅从响应中读取数据是很困难的。

我的过滤器看起来像这样:

代码语言:javascript
复制
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))
            })


        }
    }
}

我发现了这个示例: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);,但当我尝试它时,它没有包含可用于获取正文的ClientResponse对象。相反,我得到的是netty的HttpClientResponse对象,它无法获取响应体。

我搜索了无数的stackoverflow主题,涵盖了一些看起来有点相似的问题,但实际上没有一个是相同的。

我也尝试过这种方法,就像在这个https://github.com/spring-cloud/spring-cloud-gateway/issues/177#issuecomment-361411981中一样,您可以使用ServerHttpResponseDecorator读取正文。但是,只有在调用writeWith()方法时,它才会读取正文。因此,如果我想要原始响应,我必须将原始响应作为DataBuffer重新写入,以便触发writeWith。但是如果我有is作为DataBuffer,我就根本不需要整个ServerHttpResponseDecorator了。

所以,请帮帮我--我的头撞到了墙上,我想放弃这一切。我通常不会放弃,因为我觉得这应该是微不足道的,因为这是如此简单的事情:“在代理请求之后读取响应正文”。

有什么想法吗?

EN

回答 1

Stack Overflow用户

发布于 2019-12-11 21:21:45

获取可读格式的响应的一种方法是(改编自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 Connection:

代码语言:javascript
复制
            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)
            }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59286520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档