Read the body of the POST HTTPServletRequest body And then call getParameter on Tomcat

I am in a situation where my application must check the contents / data / body / payload of a POST request without changing the results of subsequent calls to getParameter.

Reading the body from the input stream:

The body can be read using InputStream from request.getInputStream or BufferedReader from request.getReader .

Reading POST parameters:

POST requests typically include request parameters in the request body. They can be obtained using getParameter .

Problem:

The first call to getParameter internally parses the input stream and inserts all parameters into the HashMap parameter. This requires the inputStream to still contain parsing content. Thus, you cannot check the contents and have a getParameter working call.

Proposed (but not sufficient) solution

Create a request wrapper that caches the input stream and returns a cache for getInputStream.

I saw that this solution is offered all over the Internet, but it does not work, because getParameter does not actually call getInputStream , but refers to the original inputBuffer buried in the request object. I tried this, both from Servlet and using a filter

The only solution I can think of involves rewriting getParameter to actually analyze the cached input stream manually. But this seems like a bad idea.

Does anyone have an alternative that works? (This is Tomcat 5.5). It seems like this should be a common use case; I can’t believe how difficult it is.

+8
java post tomcat servlets
source share
2 answers

As suggested by @caskey, a possible solution would be to use reflection to replace inputBuffer with a playable input buffer. But I did not use this approach because it felt naughty.

Instead, I created a request wrapper in a filter that reads the input stream into an array of bytes and returns a new InputStream that internally uses ByteArrayInputStream around this array for all getInputStream calls.

After reading the input stream into the byte array, I create a parameter map by analyzing the payload. I combined a superclass parameter map to support GET cases with query parameters. I overridden all getParameter * () methods to use this parameter map.

I used apache.axis.utils.IOUtils.readFully to easily read the stream into an array of bytes. And currently I am using javax.servlet.http.HttpUtils.parsePostData to parse the data in the parameter map. HttpUtils.parsePostData is not really recommended, so I will most likely replace it with a better version when I find it.

But it works, yay!

+1
source

(Which is a pretty old tomcat, I assume updating to a more modern one is not an option.)

What you want to do will require intercepting the construction of a specific HttpServletResponse object wrapping the underlying InputStream. Requires packaging that has an InputStream in an input / output stream (or equivalent).

Tomcat 5.5 is so old that I can’t even think how it will be done “normally”, but maybe you can write a filter that uses reflection to access and replace the InputStream object inside a specific request object.

+1
source

All Articles