0

I have custom Filter and I want to log body from request. But when I use ContentCachingRequestWrapper and try to call getContentAsByteArray() I always get an empty array.

@Component
public class CustomFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(CustomFilter.class);

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest requestToCache = new ContentCachingRequestWrapper(request);

        chain.doFilter(req, res);

       log.info(getRequestData(requestToCache));
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

    public static String getRequestData(final HttpServletRequest request) throws UnsupportedEncodingException {
        String payload = null;
        ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
        if (wrapper != null) {
            byte[] buf = wrapper.getContentAsByteArray();
            if (buf.length > 0) {
                payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
            }
        }
        return payload;
    }
  }

I also tried create Interceptor, but had the same problem. What am I doing wrong? Thanks for help.

2
  • Is this not caused by the fact you're creating a ContentCachingRequestWrapper before your call to getRequestData, where it's creating another ContentCachingRequestWrapper? I suspect because it reads the body when you create the first ContentCachingRequestWrapper that it can't re-read from the buffer when creating the second and therefore the body is null/empty. You could always pass the first ContentCachingRequestWrapper into your method rather than creating a second instance. Commented Nov 10, 2018 at 17:35
  • I also used it once and had the same result. Commented Nov 10, 2018 at 17:39

2 Answers 2

2

You can use the existing spring implementation by just registering this bean in a @Configuration annotated class:

@Bean
public static Filter requestLoggingFilter() {
    final CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
    loggingFilter.setIncludePayload(true);
    loggingFilter.setMaxPayloadLength(512);

    return loggingFilter;
}
Sign up to request clarification or add additional context in comments.

Comments

2

Whilst I'd recommend going with NiVer's answer, I've been looking into why this issue occurs and I can finally give you an answer.

When you create a new ContentCachingRequestWrapper, the internal ByteArrayOutputStream is initialized but no data is copied to it. The body is only written to the ByteArrayOutputStream when you call getParameter, getParameterMap(), getParameterNames() or getParameterValues(String name) methods, and even then the data is only copied if the content type contains application/x-www-form-urlencoded.

1 Comment

I saw empty array and could`t understand why. Thank you for help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.