如何在 Spring WebFlux 中记录请求和响应主体

新手上路,请多包涵

我想在带有 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 并且没有响应正文。

有没有办法访问来自某些过滤器的日志记录的完整请求和响应?我不明白什么?

原文由 Koguro 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 691
1 个回答

这或多或少类似于 Spring MVC 中的情况。

在 Spring MVC 中,您可以使用 AbstractRequestLoggingFilter 过滤器和 ContentCachingRequestWrapper 和/或 ContentCachingResponseWrapper 。这里有许多权衡:

  • 如果您想访问 servlet 请求属性,您需要实际读取和解析请求正文
  • 记录请求正文意味着缓冲请求正文,这可能会占用大量内存
  • 如果您想访问响应正文,则需要包装响应并在响应正文被写入时缓冲它,以供以后检索

ContentCaching*Wrapper 中不存在类,但您可以创建类似的类。但请记住这里的其他要点:

  • 在内存中缓冲数据以某种方式违背了反应堆栈,因为我们正在尝试使用可用资源非常有效
  • 您不应该篡改实际的数据流并且刷新的频率比预期的多/少,否则您可能会破坏流式传输用例
  • 在那个级别,您只能访问 DataBuffer 实例,它们是(大致)内存高效字节数组。这些属于缓冲池,并被回收用于其他交换。如果这些没有正确保留/释放,则会创建内存泄漏(并且缓冲数据以供以后使用肯定适合这种情况)
  • 再次在那个级别,它只是字节,您无权访问任何编解码器来解析 HTTP 正文。如果一开始就不是人类可读的,我会忘记缓冲内容

您的问题的其他答案:

  • 是的, WebFilter 可能是最好的方法
  • 不,您不应该订阅请求正文,否则您将使用处理程序无法读取的数据;你可以 flatMap 上请求和缓冲数据在 doOn 运营商
  • 包装响应应该使您可以在编写响应主体时访问它;不过不要忘记内存泄漏

原文由 Brian Clozel 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进