如何在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,没有响应正文。

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

布莱恩·克洛泽(Brian Clozel):

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

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

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

ContentCaching*WrapperWebFlux中不存在类,但是您可以创建类似的类。但请记住以下几点:

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

您问题的其他答案:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Spring'HandlerMethodArgumentResolver'中多次读取请求正文?

如何在Flask中记录请求POST正文?

当Java中的请求失败时,如何获取http响应正文?

如何在Retrofit,RxJava,Android中从所有请求发出多个请求和响应

如何在Spring RestTemplate中记录响应?

当我重定向初始请求时,如何在gin中记录响应正文

如何在杜松子酒中记录响应正文

如何在Spring Boot中将肥皂请求和带有自定义消息的响应记录到文件中?

如何在Spring MVC中记录传入请求

OkHttp如何记录请求正文

如何使用Retrofit-Android记录请求和响应正文?

如何在Spring Webflux WebExceptionHandlder中将消息写入HTTP正文

如何在JAX-RS客户端中记录请求正文

如何在Mountebank中使用代理记录请求和响应?

如何在ASP.NET Core 1.0中记录HTTP响应正文

如何在WCF跟踪中查看SOAP请求和响应

由于我们没有记录请求和响应主体,我们如何才能从错误中找出导致请求失败的错误?

测试在Jest中失败时如何打印请求和响应?

如何在Django Rest Framework中记录4XX Http状态的请求和响应?

如何在容器中记录HTTP请求和时间成本?

如何使用Wiremock在响应中返回字段中的请求正文

如何在 Spring WebFlux 中设置 ViewResolver

如何避免请求和响应中的类型字段@jsoninfotype

如何记录 HttpClient 请求,响应包括正文?

如何记录传入的请求和响应?

即使 OAuth2 验证失败,如何记录 http 请求/响应正文?

Azure API 管理记录请求和响应正文

如何在php中的Curl请求中仅获取响应的正文

如何在 Spring Boot 中使用 OpenAPI 3 从“响应”和“请求正文”中隐藏“模式”?