java.lang.IllegalStateException: Cannot call getInputStream() after getReader() has already been called for the current request

Viewed 2010

I wrote interceptor:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    log.info("[pre-handle] method: {}\tURL: {}", request.getMethod(), request.getRequestURL());
    if (HttpMethod.POST.name().equals(request.getMethod())) {
        log.info(request.getReader().lines().collect(Collectors.joining()));
    }
    return true;
}

but when I try to call controller, exception throws:

java.lang.IllegalStateException: Cannot call getInputStream() after getReader() has already been called for the current request

as I understand, getReader() calling closes InputStream & nothing comes to controller. How to fix it?

1 Answers

To read request multiple time you will need to cache your request before it is read the 1st time. More info can be read here.

Spring MVC provides the ContentCachingRequestWrapper class. It is a wrapper around the original HttpServletRequest object.

To use it, we must first create a web filter which wraps the original HttpServletRequest:

@Component
public class CachingRequestBodyFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
      throws IOException, ServletException {
        HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(currentRequest);
        chain.doFilter(wrappedRequest, servletResponse);
    }

After which you can get the byte[] content using the getContentAsByteArray method of ContentCachingRequestWrapper in your interceptor.

Related