-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Jose,

On 1/14/15 4:03 PM, Christopher Schultz wrote:
> Jose,
> 
> On 1/14/15 3:54 PM, Jose María Zaragoza wrote:
>> 2015-01-14 20:05 GMT+01:00 Christopher Schultz 
>> <ch...@christopherschultz.net>: Jose,
> 
>> On 1/14/15 8:27 AM, Jose María Zaragoza wrote:
>>>>> 2015-01-14 12:46 GMT+01:00 André Warnier <a...@ice-sa.com>:
>>>>>> Jose María Zaragoza wrote:
>>>>>>> 
>>>>>>> Hello:
>>>>>>> 
>>>>>>> I would like to create a web filter to forward some 
>>>>>>> requests to another webserver,
>>>>>>> 
>>>>>>> The filter receives an 
>>>>>>> "application/x-www-form-urlencoded" request , inspects 
>>>>>>> the value of a parameter and chooses to forward to 
>>>>>>> another remote webserver ( as a proxy )
>>>>> 
>>>>> 
>>>>> Thanks
>>>>> 
>>>>> I agree with you . I'll try to use an Apache httpd
>>>>> front-end
>>>>> 
>>>>> Anyway, I've seen that if I execute
>>>>> 
>>>>> Map<String, String[]> parameter = ((HttpServletRequest) 
>>>>> request).getParameterMap();
>>>>> 
>>>>> , then request.getInputStream is empty
>>>>> 
>>>>> 
>>>>> But if I execute
>>>>> 
>>>>> Map<String, String[]> parameter = ((HttpServletRequest) 
>>>>> request).getParameterMap(); chain.doFilter(request, 
>>>>> response);
>>>>> 
>>>>> , the next filter in the chain receives the body ( as I 
>>>>> expect it )
>>>>> 
>>>>> I don't understand this behaviour
> 
>> I think that might be a bug... calling 
>> HttpServletRequest.getParameter* should cause the request entity
>> to be parsed, as long as the content type is 
>> application/x-www-form-urlencoded. I think getParameterMap
>> counts, but I'd have to review the spec & javadoc (where some fun
>> spec requirements are hidden!).
> 
>> Anyhow, when you call HttpServletRequest.getParameter*, the 
>> container *must* consume the request, according to the spec.
> 
> 
>>> Thanks.
> 
>>> In my case, all requests to be forwarded are POST requests  ( 
>>> and content type is application/x-www-form-urlencoded )
>>> According to your reply, if I've got a chain of filters and the
>>> first one calls getParameterMap , do the next filters lose the
>>> content of the payload ?
> 
> Correct. Once the request entity has been read (which happens when
> you call request.getParameter*), it's no longer available to the
> application.
> 
>>> I tested to call several times to getParameterMap method on
>>> the same webfilter and it always returned the right values.
>>> Looks like getParameterMap doesn't consume() payload, but ...
>>> if I call getInputStream() after getParameterMap() , the stream
>>> is empty
> 
>>> I'm using Tomcat 7.0.50 and I cannot understand the logic of 
>>> this
> 
> Interesting. I find that surprising... I'll look into that.

Maybe I misunderstood you, but it sounded like it you called
getParameterMap() and then tried to read the InputStream to read the
request entity, you were still able to read it.

I just did a simple test and, of course, that's not the case at all.

When you call any of the family of getParameter* methods, the entity
will be parsed and saved by the container for the life of the request.
It doesn't matter how many times you call getParameter*, the entity
will only be parsed once, and once it's been parsed, it will no longer
be available to any other code: filter, servlet, etc.

If you call HttpServletRequest.getInputStream or
HttpServletRequest.getReader *before* any call to getParameter*, then
the container will not even attempt to parse the request entity and
everything will return null (or an empty map for the case
getParameterMap).

If you call getInputStream/getReader, the container concludes that the
application (filter, servlet, whatever) has assumed responsibility for
handling the post data and therefore doesn't do anything with it itself.

So, back to your proxy servlet.

If you want to read POST data to decide how to route the request,
you'll have to do it by handling the request entity yourself. If you
don't do it yourself, you won't be able to reconstruct the exact byte
stream that the client sent, which is part of the deal when you are a
proxy. If you don't want to be a formal proxy, then you can cheat and
use getParameter* and then do a messy re-construction of the original
request and send *that* to the other back-end server.

Most proxies make their decisions based upon information found in the
HTTP headers to avoid this exact problem.

If you *must* make your decisions based upon the contents of the
message, then you will have to handle a lot of buffering and plumbing
code to make it all work.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJUt985AAoJEBzwKT+lPKRYoHEQAMm5FBnv+mKu0V6ZObzyYCZt
6YzeNnk+rgR7sEAHNBJ2rOiMp/JEydgT896yw1qN+YUiYT33Mf0RMiYsJKhUaf/P
KGjuRoHT60AibP2r+mi1LY5o3Wt+EKZ/lFIGBBCyfPDElYq7iokjYZDfedg1TiIg
DBjucF29K+mVaq8wFBXHVK64bJo9Jfj87YO5x8syDJFgV57mELAMofKv5+3yL8Lz
3n7TcEJr2uoxZj8qVpRWmvdSkBN/p4drXW/kDtDf/IbPz3Lf0WC97Opj0QxuoeuX
aKwi94AyUH5fNai/0pSaTFQmnaqwhKDXaJhaaAv0YHcN/StyRO+JNz6rkCshxRD7
MvhzudpLDPbrZjN0McuEY9H43qqzNoAzh17i97PcEmHC2ZZcGtPzW/tWFV6D0x+b
xnqu5+ysNKbl3mmZd92FD954lGWNUlLGKtODOdHmmu1zDRyIt/txS6f3T2ySFZJz
nzz/t0BO70fZI5ST5FvZbmtqQvv6WXVJ/4Gfhr7rb4VoMRTWMSTlvpRyI3fhdglx
ruDaZnvP26bLERgwNr6NPH80Tlv6SkXxtHljIdC2w9iBmNlJ/QI5T1kO5SFFpvOW
BYg+8ZcB/JWvvS593x9IAocD/OVnarJPanWKmIoR/3Ms4NJKWiWfE0mtlOjZrCpb
Q33GfkPl5NOWNXMUyY3u
=FOgg
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to