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

Reply via email to