Reading InputStream twice
843840Apr 2 2002 — edited Jan 5 2009I am creating a filter to check the contents of a form (POST) request going to servlet. The form body is not in name/value pair format, but only has a value (not my servlet--I'm just the middleman). The destination servlet reads the request with getInputStream(). I need to read the contents to block certain requests. If you just do getInputStream() or getReader(), the destination servlet throws an error because you can only read the input stream once.
I created a wrapper class using HttpServletRequestWrapper. In that class's constructor, I store the input stream with getInputStream() in an instance variable. I override getInputStream and pass the stored input stream. That should enable me to read the input stream in my own call to the overriden getInputStream(). I feed it to a BufferedReader and read the contents into a StringBuffer.
However, when I try to process the contents of the input stream in my filter, it seems to affect the contents of the input stream. The destination servlet complains that the request cannot be read correctly.
Does reading an input stream somehow change it? If so, is there another way to read those contents without affecting them?
Code snippet from doFilter():
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws ServletException, IOException {
// Cast to HttpServlet to get request method
HttpServletRequest reqHttp = (HttpServletRequest) request;
// Create wrapper for request -- extended class also gets input stream
reqWrapper reqWrap = new reqWrapper(reqHttp);
// Get request body
ServletInputStream reqBody = reqWrap.getInputStream();
BufferedReader brReq =
new BufferedReader(new InputStreamReader(reqBody));
// Read request from body
StringBuffer sb = new StringBuffer();
String line; // everything OK till here
// *** next line causes parsing error in destination servlet ***
while ((line = brReq.readLine()) != null) { sb.append(line);
}
String formReq = sb.toString();
// (more invening code to examine the string before chaining)
chain.doFilter(reqWrap, response);
}