I've added a filter to my application which simply logs certain things about a request. Some of my servlets read from ServletRequest#getInputStream
. Since adding this filter, those servlets that read from ServletRequest#getInputStream
no longer work as the input stream is empty. Disabling the filter by simply commenting it out from my web.xml
resolves the issue.
Why is this happening and is there a way to use a filter without it messing up the ServletRequest#getInputStream
?
The filter is actually Tomcat's RequestDumperFilter
included in one of its example web apps. I'll only include the doFilter
method as that is the important part. If you want to see the entire thing, I've put it up on PasteBin.
/**
* Time the processing that is performed by all subsequent filters in the
* current filter stack, including the ultimately invoked servlet.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
if (filterConfig == null)
return;
// Render the generic servlet request properties
StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw);
writer.println("Request Received at " +
(new Timestamp(System.currentTimeMillis())));
writer.println(" characterEncoding=" + request.getCharacterEncoding());
writer.println(" contentLength=" + request.getContentLength());
writer.println(" contentType=" + request.getContentType());
writer.println(" locale=" + request.getLocale());
writer.print(" locales=");
Enumeration locales = request.getLocales();
boolean first = true;
while (locales.hasMoreElements()) {
Locale locale = (Locale) locales.nextElement();
if (first)
first = false;
else
writer.print(", ");
writer.print(locale.toString());
}
writer.println();
Enumeration names = request.getParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
writer.print(" parameter=" + name + "=");
String values[] = request.getParameterValues(name);
for (int i = 0; i < values.length; i++) {
if (i > 0)
writer.print(", ");
writer.print(values[i]);
}
writer.println();
}
writer.println(" protocol=" + request.getProtocol());
writer.println(" remoteAddr=" + request.getRemoteAddr());
writer.println(" remoteHost=" + request.getRemoteHost());
writer.println(" scheme=" + request.getScheme());
writer.println(" serverName=" + request.getServerName());
writer.println(" serverPort=" + request.getServerPort());
writer.println(" isSecure=" + request.isSecure());
// Render the HTTP servlet request properties
if (request instanceof HttpServletRequest) {
writer.println("---------------------------------------------");
HttpServletRequest hrequest = (HttpServletRequest) request;
writer.println(" contextPath=" + hrequest.getContextPath());
Cookie cookies[] = hrequest.getCookies();
if (cookies == null)
cookies = new Cookie[0];
for (int i = 0; i < cookies.length; i++) {
writer.println(" cookie=" + cookies[i].getName() +
"=" + cookies[i].getValue());
}
names = hrequest.getHeaderNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String value = hrequest.getHeader(name);
writer.println(" header=" + name + "=" + value);
}
writer.println(" method=" + hrequest.getMethod());
writer.println(" pathInfo=" + hrequest.getPathInfo());
writer.println(" queryString=" + hrequest.getQueryString());
writer.println(" remoteUser=" + hrequest.getRemoteUser());
writer.println("requestedSessionId=" +
hrequest.getRequestedSessionId());
writer.println(" requestURI=" + hrequest.getRequestURI());
writer.println(" servletPath=" + hrequest.getServletPath());
}
writer.println("=============================================");
// Log the resulting string
writer.flush();
filterConfig.getServletContext().log(sw.getBuffer().toString());
// Pass control on to the next filter
chain.doFilter(request, response);
}
Conclusion
From what I've read by Googling, any of the following methods will render getInputStream
empty if called first:
getParameter
getParameterNames
getParameterValues
getParameterMap
Thanks SimoneGianni for pointing me in the right direction:
Here are some sources
- http://www.xyzws.com/Servletfaq/what-is-the-getinputstream-of-servletrequest-for/23
- http://davidhuo.blogspot.com/2006/05/be-careful-with-httpservletrequestgeti.html
- https://issues.apache.org/bugzilla/show_bug.cgi?id=47410
This person actually had a similar issue and created his own wrapper class as a work-around.