给定一个交换使用WebClient
,按自定义过滤ExchangeFilterFunction
:
@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
return next.exchange(request)
.doOnSuccess(response -> {
// ...
});
}
尝试使用多次访问响应主体response.bodyToMono()
将导致底层 HTTP 客户端连接器抱怨只允许一个接收器。 AFAIK,没有办法访问主体的发布者来cache()
它的信号(我不确定这是否是一个好主意,从资源角度来看),以及没有办法改变或装饰response
对象以允许访问其主体的方式(就像可以使用ServerWebExchange
在服务器端)。
这是有道理的,但我想知道是否有任何方法可以通过像这样的过滤器形式订阅响应正文的发布者。我的目标是记录给定发送/接收的请求/响应WebClient
实例。
我是反应式编程的新手,所以如果这里有任何明显的禁忌,请解释一下:)
仅用于记录,您可以添加窃听HttpClient
如中所述这个答案 https://stackoverflow.com/a/55790675/2161004.
但是,您的问题在日志记录之外的更一般意义上也很有趣。
一种可能的方法是创建一个副本ClientResponse
具有先前请求正文副本的实例。这可能违反反应原则,但它为我完成了工作,而且考虑到我的客户中响应机构的规模较小,我认为没有太大的缺点。
就我而言,我需要这样做,因为发送请求的服务器(在我的控制之外)使用 HTTP 状态200 Ok
即使请求失败。因此,我需要查看响应正文,以找出是否出现问题以及原因是什么。就我而言,如果错误消息表明会话已过期,我会从缓存中逐出请求标头中的会话 cookie。
这些是步骤:
- 获取字符串 Mono 形式的响应正文(参见
(1)
).
- 返回一个
Mono.Error
如果检测到错误(参见(2)
).
- 使用响应正文的字符串构建原始响应的副本(参见
(3)
).
您还可以使用对ObjectMapper
将 String 解析为对象进行分析。
请注意,我是用 Kotlin 编写的,但它应该很容易适应 Java。
@Component
class PeekIntoResponseBodyExchangeFilterFunction : ExchangeFilterFunction {
override fun filter(request: ClientRequest, next: ExchangeFunction): Mono<ClientResponse> {
return next.exchange(request)
.flatMap { response ->
// (1)
response.bodyToMono<String>()
.flatMap { responseBody ->
if (responseBody.contains("Error message")) {
// (2)
Mono.error(RuntimeException("Response contains an error"))
} else {
// (3)
val clonedResponse = response.mutate().body(responseBody).build()
Mono.just(clonedResponse)
}
}
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)