André, On 11/23/15 11:18 AM, André Warnier (tomcat) wrote: > On 23.11.2015 16:31, Mark Thomas wrote: >> On 23/11/2015 14:30, Roel Storms wrote: >>> Hello, >>> >>> I am working on a Valve that does some integrity checking on HTTP >>> requests >>> (the details aren't important) where I need this valve to have access to >>> the HTTP request body as well. I used request.getInputStream to fetch >>> the >>> data. However when a web application makes use of my valve, the >>> getParameter method does not return the parameters submitted via POST >>> anymore. This is documented behavior according to the spec of >>> ServletRequest ( >>> https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/ServletRequest.html#getInputStream() >>> >>> ). >>> >>> I was wondering why it was designed this way, >> >> Given the potential size of a request body, streaming is the only viable >> option. >> >>> since numerous complaints >>> have arisen from this behavior and some ugly workarounds have been >>> devised >>> which unfortunately stop working from Tomcat 7 (servlet 3.0): >>> >>> https://stackoverflow.com/questions/10210645/http-servlet-request-lose-params-from-post-body-after-read-it-once >>> >>> >>> This shows how easily code like this could break. >> >> What that shows is the folks haven't thought through what they are >> trying to do. Consider the following: >> >> Tomcat provides request R. >> Filter reads request body using R.getInputStream(). >> Filter caches request body. >> Filter wraps request R to provide R', over-riding getInputStream() to >> provide the cached body. >> Filter passes R' to the application. >> Application calls R'.getParameter() >> R'.getParameter() calls R.getParameter() >> >> Keep in mind at this point R has zero knowledge of R'. >> >> R calls getInputStream() to read request body but that InputStream has >> already been read. >> >> The problem is the wrapper, R'. Over-riding getInputStream() is not >> enough. It needs to over-ride every method that may access that >> InputStream. Which is non-trivial because it means re-implementing a lot >> of functionality the container would normally provide for you out of the >> box. >> >>> Overwriting getInputStream to return a cached version doesn't work >>> anymore >> >> Nope. That never worked. See my explanation above. >> >>> since the parameter attribute isn't populated by using >>> getInputStream. How >>> exactly it is populated remains a mystery to me. Any advice on how to >>> solve >>> this properly? >> >> Write a better wrapper. >> >>> Performing an integrity check without getInputStream or getReader but >>> with >>> getParameters, will not work if the data submitted is not in the >>> expected >>> format. >> >> See above. >> >> Mark >> > > To emphasize a point made by Mark above : a POST body can potentially > contain one or more <input type="file" ..> elements. So imagine a POST > which contains a 50 MB uploaded file. > You'd need to read it once (for your Valve) and cache it, then re-read > the cached version to parse it for parameters. That would have a > serious impact on performance. > (That's what Mark means by "streaming.."). > And because it is a Valve, it would run before the request has been > mapped to any application, so the hit would be for all applications in > the server.
Valves can be placed in a number of different locations. I believe all Valves will fire after the host and application have been mapped, but all Valves will certainly fire before any application code (e.g. Filters) will fire. -chris --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org