HttpServletRequestWrapper example – read httpservletrequest twice

Recently I came through a requirement in which I have to read HttpServletRequest body twice and the pass the request again to filter chain for normal application flow. Then I created below given Java class which can used inside a servlet filter to intercept the request, read request body content and then pass the request again to servlet filter chain for further processing.

1. HttpServletRequestWrapper example

This is the sourcecode of custom implementation of HttpServletRequestWrapper class. Please note that I am using Servlets 2.5 specification here, because I had to work on some legacy applications. Feel free to change the implementation as per latest servlet specification.

This class cab be see as example to read inputstream twice, but it is not.

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class RequestWrapper extends HttpServletRequestWrapper {
	private final String body;

	public RequestWrapper(HttpServletRequest request) throws IOException 
	{
		//So that other request method behave just like before
		super(request);
		
		StringBuilder stringBuilder = new StringBuilder();
		BufferedReader bufferedReader = null;
		try {
			InputStream inputStream = request.getInputStream();
			if (inputStream != null) {
				bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
				char[] charBuffer = new char[128];
				int bytesRead = -1;
				while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
					stringBuilder.append(charBuffer, 0, bytesRead);
				}
			} else {
				stringBuilder.append("");
			}
		} catch (IOException ex) {
			throw ex;
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException ex) {
					throw ex;
				}
			}
		}
		//Store request pody content in 'body' variable 
		body = stringBuilder.toString();
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
		ServletInputStream servletInputStream = new ServletInputStream() {
			public int read() throws IOException {
				return byteArrayInputStream.read();
			}
		};
		return servletInputStream;
	}

	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(this.getInputStream()));
	}

	//Use this method to read the request body N times
	public String getBody() {
		return this.body;
	}
}

2. HttpServletRequestWrapper usage

Use wrapper to modify request parameters in servlet filter. It will help to servlet read request body twice.

To use this class, you must first add a servlet filter mapping in web.xml.

<filter>
	<filter-name>cacheFilter</filter-name>
	<filter-class>com.howtodoinjava.filter.RESTCacheFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>cacheFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

Above filter mapping will invoke the filter at all requests because we mapped it to wildcard /*.

3. How to read request body twice in servlet filter

Now you can add a servlet filter java class in your code like this.

public class CacheFilter implements Filter {

	private static final Logger LOGGER = LoggerFactory.getLogger(CacheFilter.class);
	private static final String INDEX_DIR = "c:/temp/cache";

	private FilterConfig filterConfig = null;

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		request = new RequestWrapper((HttpServletRequest) request);

		//Read request.getBody() as many time you need

		chain.doFilter(request, response);
	}

	public void init(FilterConfig filterConfiguration) throws ServletException {
		this.filterConfig = filterConfiguration;
	}

	public void destroy() {
		this.filterConfig = null;
	}
}

In this servlet filter, you can read the http request body N number of times and then pass to filter chain and it will work just fine.

It’s a small utility class and may not be needed in most of the cases. But when it’s needed – you will know it.

4. Summary

You must be aware, by deafult, the http request body can be read only once. If you read the body in a filter, the target servlet will not be able to re-read it and this will also cause IllegalStateException.

Using above given HttpServletRequestWrapper, you can read HTTP request body and then the servlet can still read it later. Essentially, request body content is cached inside wrapper object so it can be N number of times in complete request lifecycle.

Drop me your questions in comments section.

Happy Learning !!

Leave a Reply

11 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial