2015-11-23 16:31 GMT+01:00 Mark Thomas <ma...@apache.org>:

> 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.
>
> A better wrapper would need to implement every method using the stream. To
get a correct output from parseParameters it doesn't suffice to override
readPostBody and readChunkedPostBody since these are overridden in the
wrapper but the implementation of parseParameter in the Request won't use
them. Overriding parseParameters as well, can't be done since it uses a lot
of protected flags (parametersParsed, usingInputStream, usingReader,...).
This would mean overriding almost the entire Request. Every time you need a
protected attribute or operation in your overriding implementation, you
need to override this attribute and operation as well. In the end you would
copy almost the entire request.

> 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 unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>

Reply via email to