4

When you try to access the raw InputStream of a x-www-form-urlencoded servlet request, the stream could have already been indirectly consumed by a prior access to the parameters (e.g., via ServletRequest#getParameterMap()) of the request. This feature (bug?) has already been documented in the section SRV.3.1.1 of the Servlet spec and there are other people who have been bitten by this as well.

This indirect stream consumption makes it, to the best of my knowledge, impossible to mirror the InputStream, which is exactly what we are trying to achieve in HRRS. Hence, I try to re-construct the InputStream from request parameters. This, as you can imagine, a really nasty hack which I am not fond of either. Further, to make the things worse, when servlet pushes the form parameters into request parameter map, it merges them with query parameters too. Now you need to manually parse both request and query parameters to figure out the initial form parameters. A total shipwreck.

Any ideas on how to replace this hack with a proper solution?

Edit: Dear SO Java-badge owners, this is not a duplicate question. Please see the Tomcat bug report before marking the post as duplicate. Even if HRRS is the first filter in the list, it is not consuming InputStream, it is just wrapping the InputStream and passing along the wrapped request along the chain. Problem is, getParameter() calls in Tomcat is using an internal reference to the InputStream (that is, o.a.c.connector.Request#getStream()) and not calling javax.servlet.ServletRequest#getInputStream(). Hence, InputStream gets indirectly consumed without the wrapped one getting used at all. (See o.a.c.connector.Request#readPostBody() source code for details.)

Volkan Yazıcı
  • 1,530
  • 1
  • 15
  • 28
  • Have you found any solution for this yet? I need to get an access to the raw body in order to validate the signature of it that used a signing secret and a standard HMAC-SHA256 keyed hash – Leffchik Jul 20 '19 at 23:59
  • @Leffchik, yes, [I figured it is not solvable](https://github.com/vy/hrrs#caveats). – Volkan Yazıcı Jul 22 '19 at 07:34

1 Answers1

0

I don't think it is possible to completely recreate the original request in all cases. The order of request parameters will be lost for example.

For a tool like this I think it is perfectly acceptable to expect to be the outermost filter. That way you shouldn't have the problem in the first place. But maybe I'm missing something?

Guus Bloemsma
  • 31
  • 1
  • 6
  • Even if HRRS is the first filter in the list, it is *not* consuming `InputStream`, it is just wrapping the`InputStream` and passing along the wrapped request along the chain. Problem is, `getParameter()` calls in Tomcat is using an internal reference to the `InputStream`, not calling `getInputStream()`. Hence, `InputStream` gets indirectly consumed without the wrapped one getting used at all. – Volkan Yazıcı Sep 19 '17 at 06:33
  • For the records, see `o.a.c.connector.Request#readPostBody()` for details. – Volkan Yazıcı Sep 19 '17 at 07:15