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);
}
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
This person actually had a similar issue and created his own wrapper class as a work-around.
If you call getParameters, getParameterNames and similar methods, you COULD interfere with getInputStream or getReader. This isn't stated clearly enough in servlet documentation, but there are some warnings about the opposite (getInputStream interfering with getParameter) in the official servlet javadocs (since 1.3, see http://download.oracle.com/javaee/1.3/api/javax/servlet/ServletRequest.html#getParameter(java.lang.String) )
Are you seeing this problem on POSTs? Since POST requests encode parameters as request body, to read the parameters you actually have to consume (the container does this for you) the input stream.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With