4

Followed the post post to create a filter to get the request and response bodies.

Spring Boot 2 filter (HttpTraceFilter) appears to be a bit different so not sure how to set the http trace properties from the request attributes.

Any help much appreciated!

@Component
public class RequestTraceFilter extends HttpTraceFilter {

/**
 * Create a new {@link HttpTraceFilter} instance.
 *
 * @param repository the trace repository
 * @param tracer     used to trace exchanges
 */
public RequestTraceFilter(HttpTraceRepository repository,
        HttpExchangeTracer tracer) {
    super(repository, tracer);
}

//TODO override the filter :(
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws
        ServletException,
        IOException {

    ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
    ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

    filterChain.doFilter(requestWrapper, responseWrapper);
    responseWrapper.copyBodyToResponse();
    request.setAttribute("REQUEST_BODY", getRequestBody(requestWrapper));
    request.setAttribute("RESPONSE_BODY", getResponseBody(responseWrapper));

    super.doFilterInternal(requestWrapper, responseWrapper, filterChain);

}

private String getRequestBody(ContentCachingRequestWrapper request) {
    ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
    String characterEncoding = wrapper.getCharacterEncoding();
    return getPayload(wrapper.getContentAsByteArray(), characterEncoding);
}

private String getResponseBody(ContentCachingResponseWrapper response) {
    ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
    return getPayload(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding());
}

public String getPayload(byte[] buf, String characterEncoding) {
    String payload = null;
    if (buf.length > 0) {
        try {
            payload = new String(buf, 0, buf.length, characterEncoding);
        }
        catch (UnsupportedEncodingException ex) {
            payload = "[unknown]";
        }
    }
    return payload;
}

}

Brian Clozel
  • 56,583
  • 15
  • 167
  • 176
kiara
  • 71
  • 4

2 Answers2

3

Received a response in github from wilkinsona:

https://github.com/spring-projects/spring-boot/issues/12953

HTTP tracing in 2.0 is intentionally less flexible than it was in 1.5. The flexibility of the implementation in 1.5 caused a number of problems and made it impossible to support on top of WebFlux, Spring MVC, and Jersey. Tracing the request and response body has never been supported out of the box. Support for tracing parameters was dropped as, when the request is POSTed form data, it requires reading the entire request body. If you want to capture one or both of these, and I would recommend that you don't, you should implement your own endpoint.

kiara
  • 71
  • 4
0

With a webflux reactive stack, it is possible to capture http request and response body using spring-cloud-gateway and inject them into actuator httptrace by defining a custom HttpTraceWebFilter.

See full associated code at https://gist.github.com/gberche-orange/06c26477a313df9d19d20a4e115f079f

This requires quite a bit of duplication, hopefully springboot team will help reduce this duplication, see related https://github.com/spring-projects/spring-boot/issues/23907

ps: This answer duplicates https://stackoverflow.com/a/64538270/1484823, feel free to remove it

Guillaume Berche
  • 3,049
  • 2
  • 17
  • 18