我希望使用Kotlin在Spring WebFlux上的REST API中集中记录请求和响应 . 到目前为止,我已经尝试过这种方法
@Bean
fun apiRouter() = router {
(accept(MediaType.APPLICATION_JSON) and "/api").nest {
"/user".nest {
GET("/", userHandler::listUsers)
POST("/{userId}", userHandler::updateUser)
}
}
}.filter { request, next ->
logger.info { "Processing request $request with body ${request.bodyToMono<String>()}" }
next.handle(request).doOnSuccess { logger.info { "Handling with response $it" } }
}
这里请求方法和路径日志成功,但正文是 Mono
,那么我应该如何记录呢?应该是相反的方式,我必须订阅请求正文 Mono
并将其记录在回调中?另一个问题是这里的 ServerResponse
接口无法访问响应主体 . 我怎么能在这里得到它?
我试过的另一种方法是使用 WebFilter
@Bean
fun loggingFilter(): WebFilter =
WebFilter { exchange, chain ->
val request = exchange.request
logger.info { "Processing request method=${request.method} path=${request.path.pathWithinApplication()} params=[${request.queryParams}] body=[${request.body}]" }
val result = chain.filter(exchange)
logger.info { "Handling with response ${exchange.response}" }
return@WebFilter result
}
同样的问题:请求正文是 Flux
,没有响应正文 .
有没有办法从某些过滤器访问完整的请求和响应?我不明白什么?
5 回答
布莱恩说的话 . 此外,日志记录请求/响应主体在任何时候都不具有完整内容,除非您缓冲它,这会破坏整个点 . 对于小的请求/响应,你可以逃避缓冲,但为什么要使用反应模型(除了给你的同事留下深刻印象:-))?
我可以想到的记录请求/响应的唯一原因是调试,但是使用反应式编程模型,调试方法也必须进行修改 . Project Reactor doc有一个很好的调试部分,你可以参考:http://projectreactor.io/docs/core/snapshot/reference/#debugging
这或多或少类似于Spring MVC中的情况 .
在Spring MVC中,您可以使用
AbstractRequestLoggingFilter
过滤器和ContentCachingRequestWrapper
和/或ContentCachingResponseWrapper
. 这里有许多权衡:如果您想访问servlet请求属性,则需要实际读取和解析请求主体
记录请求体意味着缓冲请求体,它可以使用大量的内存
如果您正在编写'd like to access the response body, you need to wrap the response and buffer the response body as it',以便以后检索
WebFlux中不存在
ContentCaching*Wrapper
类,但您可以创建类似的类 . 但请记住其他要点:内存中的
缓冲数据以某种方式与反应堆栈相反,因为我们正在尝试使用可用资源非常高效
你不应该篡改实际的数据流并且比预期更多/更少的冲洗,否则你冒着打破流式使用案例的风险
在该级别,您只能访问
DataBuffer
实例,这些实例是(大致)内存高效的字节数组 . 那些属于缓冲池,并被回收用于其他交换 . 如果没有正确保留/释放它们,则会创建内存泄漏(缓冲数据以供以后使用,这当然适合这种情况)再次在该级别,它可以访问任何解析HTTP正文的编解码器 . 我首先不是人类可读的
您问题的其他答案:
是的,
WebFilter
可能是最好的方法不,你不应该使用处理程序无法读取的数据;你可以
flatMap
对doOn
运算符中的请求和缓冲区数据包装响应应该让你访问响应主体,因为它忘记了内存泄漏,尽管
我没有找到记录请求/响应主体的好方法,但如果您只对元数据感兴趣,那么您可以像下面这样做 .
我是Spring WebFlux的新手,我不知道如何在Kotlin中做到这一点,但应该与使用WebFilter的Java相同:
这里有一些测试:github
我认为这就是 Brian Clozel (@ brian-clozel)的含义 .
您实际上可以为Netty和Reactor-Netty启用DEBUG日志记录,以查看正在发生的事情的全貌 . 你可以玩下面的内容,看看你想要什么,不要 . 那是我能做的最好的 .