Tomcat filter negatively affects the request input stream (empty input stream)

I added a filter to my application that just logs some things about the request. Some of my servlets are reading from ServletRequest#getInputStream . Since adding this filter, those servlets that read from ServletRequest#getInputStream no longer work, because the input stream is empty. Disabling the filter, just commenting it out from my web.xml , fixes the problem.

Why is this happening, and is there a way to use a filter without using it ServletRequest#getInputStream ?

The filter is actually Tomcat RequestDumperFilter included in one of its sample web applications. I will only include the doFilter method, as this is an important part. If you want to see everything, I put it 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 read Googling , any of the following methods will display getInputStream empty if called first:

  • getParameter
  • getParameterNames
  • getParameterValues
  • getParameterMap

Thanks to SimoneGianni for pointing me in the right direction:

Here are some sources

This person really had a similar problem, and he created his own wrapper class to work with.

+6
source share
2 answers

If you call getParameters, getParameterNames and similar methods, you MAY interfere with getInputStream or getReader. This is not clearly indicated in the servlet documentation, but there are some warnings to the contrary (getInputStream that prevent getParameter) in the official javadocs servlet (starting from 1.3, see http://download.oracle.com/javaee/1.3/api/javax/servlet /ServletRequest.html#getParameter(java.lang.String ))

Do you see this problem in POST? Since POST requests encoding parameters as the body of the request, to read the parameters that you really should consume (the container does this for you) by the input stream.

+3
source

Wow. This one good. I'm sure RequestDumper should parse the entire InputStream, well, a request dump, and so the InputStream is empty. I think you cannot use RequestDumper in front of any servlet that getInputStream plans to do. However, I am at a loss what your options are from this point. Perhaps a dump of parameters that interest you directly from HttpRequest AFTER chain.doFilter (request, response); call me.

-1
source

Source: https://habr.com/ru/post/893300/


All Articles