如何在Spring WebFlux中记录请求和响应正文 [英] How to log request and response bodies in Spring WebFlux

查看:1336
本文介绍了如何在Spring WebFlux中记录请求和响应正文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在带有Kotlin的Spring WebFlux上的REST API中集中记录请求和响应.到目前为止,我已经尝试过这种方法

I want to have centralised logging for requests and responses in my REST API on Spring WebFlux with Kotlin. So far I've tried this approaches

@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接口无法访问响应主体.我怎么在这里买?

Here request method and path log successfully but the body is Mono, so how should I log it? Should it be the other way around and I have to subscribe on request body Mono and log it in the callback? Another problem is that ServerResponse interface here doesn't have access to the response body. How can I get it here?

我尝试过的另一种方法是使用WebFilter

Another approach I've tried is using 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,没有响应正文.

Same problem here: request body is Flux and no response body.

是否可以通过某些过滤器访问完整的请求和响应以进行日志记录?我不明白吗?

Is there a way to access full request and response for logging from some filters? What don't I understand?

推荐答案

这与Spring MVC中的情况或多或少相似.

This is more or less similar to the situation in Spring MVC.

在Spring MVC中,可以使用AbstractRequestLoggingFilter过滤器和ContentCachingRequestWrapper和/或ContentCachingResponseWrapper.这里有很多折衷:

In Spring MVC, you can use a AbstractRequestLoggingFilter filter and ContentCachingRequestWrapper and/or ContentCachingResponseWrapper. Many tradeoffs here:

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

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

ContentCaching*Wrapper classes don't exist in WebFlux but you could create similar ones. But keep in mind other points here:

  • 在内存中缓冲数据以某种方式违反了反应堆,因为我们正在尝试使用可用资源来提高效率
  • 您不应该篡改实际的数据流,并且不应该频繁/频繁地刷新数据,否则就有可能破坏流式传输用例的风险
  • 在该级别的
  • 中,您只能访问DataBuffer实例,这些实例(大约)是内存有效的字节数组.这些属于缓冲池,并被回收以用于其他交换.如果未正确保留/释放这些内存,则会造成内存泄漏(并且缓冲数据以供日后使用肯定适合这种情况)
  • 再次在该级别上,它只有字节,您无权访问任何编解码器来解析HTTP正文.如果最初不是人类可读的内容,我会忘记缓冲内容
  • buffering data in memory somehow goes against the reactive stack, since we're trying there to be very efficient with the available resources
  • you should not tamper with the actual flow of data and flush more/less often than expected, otherwise you'd risk breaking streaming uses cases
  • at that level, you only have access to DataBuffer instances, which are (roughly) memory-efficient byte arrays. Those belong to buffer pools and are recycled for other exchanges. If those aren't properly retained/released, memory leaks are created (and buffering data for later consumption certainly fits that scenario)
  • again at that level, it's only bytes and you don't have access to any codec to parse the HTTP body. I'd forget about buffering the content if it's not human-readable in the first place

您问题的其他答案:

  • 是的,WebFilter可能是最好的方法
  • 不,您不应该订阅请求正文,否则您将消耗处理程序将无法读取的数据;您可以在请求上flatMap并在doOn运算符中缓冲数据
  • 包装响应应该使您可以访问正在编写的响应正文;不过不要忘记内存泄漏
  • yes, the WebFilter is probably the best approach
  • no, you shouldn't subscribe to the request body otherwise you'd consume data that the handler won't be able to read; you can flatMap on the request and buffer data in doOn operators
  • wrapping the response should give you access to the response body as it's being written; don't forget about memory leaks, though

这篇关于如何在Spring WebFlux中记录请求和响应正文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆