I have a Spring Boot API in Scala with multiple endpoints. All endpoints are async and return DeferredResult
. I want to use filters to log response body in some cases. I have created a filter with order 1 to cache requests and response as below:
@Component
@Order(1)
class ContentCachingFilter extends OncePerRequestFilter {
override def doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain): Unit = {
val requestToCache = new ContentCachingRequestWrapper(request)
val responseToCache = new ContentCachingResponseWrapper(response)
filterChain.doFilter(requestToCache, responseToCache)
responseToCache.copyBodyToResponse()
}
}
My logging filter is similar to below (removed domain specific logic):
@Component
@Order(2)
class RequestResponseLoggingFilter extends OncePerRequestFilter {
override def doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain): Unit = {
logger.info(
s"Request -> URL : ${request.getMethod} ${request.getRequestURI} ${request.getParameterMap.asScala.stringRepresentation()}")
logger.debug(
s"Request Headers -> Content-type : ${request.getContentType} \\n Headers : ${new ServletServerHttpRequest(request).getHeaders}")
filterChain.doFilter(request, response)
logger.info(s"Response -> Status : ${response.getStatus}")
}
}
I have to use ContentCachingResponseWrapper
because I want to log the response body. However, even without trying to log the response body and just by introducing ContentCachingResponseWrapper
, I don't get any response for calls to any endpoint. A local running instance returns an output like this on curl:
HTTP/1.1 200
Content-Type: application/json
Content-Length: 197
.
.
.
<
* transfer closed with 197 bytes remaining to read
* stopped the pause stream!
* Closing connection 0
curl: (18) transfer closed with 197 bytes remaining to read
If I remove the ContentCachingFilter
, the logging filter above works fine but if I try to log response body, the response stream is consumed and the response is no longer generated. Hence I need to use ContentCachingFilter
.
I did find out that all this works if the endpoints are synchronous. Could someone help me find out what is the problem and how to make this work with asynchronous endpoint?