views:

2023

answers:

5

I'm working on legacy code and need to make a patch.

The problem: an ancient application sends bad HTTP POST requests. One of the parameters is not URL encoded. I know that this parameter always comes last and I know it's name. I'm now trying to fix it on the server side which is running inside tomcat.

This parameter is not accessible via standard getParameter method of HttpServletRequest, since it's malformed. Method simply returns null. But when I manually read the whole body of request through ServletInputStream all the other parameters disappear. Looks like underlying classes can't parse contents of ServletInputStream since it's drained out.

So far I've managed to make a wrapper that reads all parameters from body and overrides all parameter access methods. But if any filter in the chain before mine will try to access any parameter, everything will break since ServletInputStream will be empty.

Can I somehow evade this problem? May be there's different approach?

To summarize, If I'll read raw request body in the filter, parameters will disappear from the request. If I read single parameter, ServletInputStream will become empty and manual processing will be impossible. Moreover, it's impossible to read malformed parameter via getParameter method.

+2  A: 

Rather than overriding methods, why don't you install a servlet filter which rewrites the request?

Jason Hunter has a pretty good article on filters.

Jon Skeet
+1  A: 

You could write your own Servlet Filter and hopefully ensure that it appears first in the chain. Then wrap the ServletRequest object in something that will handle the re-writing where needed. Have a look at the Programming Customized Requests and Responses section of http://java.sun.com/products/servlet/Filters.html

------ Update ------

I must be missing something. You say you can read the request body and read the parameters yourself. Couldn't you then ensure your filter is first, wrap the ServletRequest object, read, process and store the parameters, pass your request object up the chain and offer the parameters you stored instead of the original ones?

Matt Large
I can read all parameters except broken one. I can only read broken parameter via ServletInputStream. When I use input stream, all other parameters disappear. If I parse all parameters from input stream, sometimes servlets later in the chain break.It's complicated =)
clorz
A: 

Solution I've found:

It's not enough to just redefine parameter accessing methods. Several things must be done.

  1. A filter is needed where request will be wrapped.
  2. A custom HttpRequestWrapper is needed with all parameter access methods overridden. Request body should be parsed in constructor and stored as a field.
  3. getInputStream and getReader methods should be redefined as well. They return values depend on the stored request body.
  4. Custom class extending ServletInputStream is required since this one is abstract.

This 4 combined will allow you to use getParameter without interference with getInputStream and getReader methods.

Mind that manual request parameter parsing may get complicated with multipart requests. But that's another topic.

clorz
A: 
A: 

Can you post the rest of your HttpServletRequestWrapper? The class got prematurely cut off in your posting. Maybe there is a max length for a post.

Stan
clorz, would you mind sharing your code for your 4 step solution to this problem?
Stan