Bug 49779 - 501 Method not implemented with successive POST requests
501 Method not implemented with successive POST requests
Status: RESOLVED FIXED
Product: Tomcat 7
Classification: Unclassified
Component: Catalina
7.0.0
PC Windows XP
: P2 normal (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2010-08-19 05:47 UTC by hanswaehne
Modified: 2011-10-20 12:13 UTC (History)
1 user (show)



Attachments
client wire/context log, client code, webapp code (469.69 KB, application/zip)
2010-08-19 05:47 UTC, hanswaehne
Details

Note You need to log in before you can comment on or make changes to this bug.
Description hanswaehne 2010-08-19 05:47:51 UTC
Created attachment 25911 [details]
client wire/context log, client code, webapp code

An unexpected HTTP 501 occurs if using HttpComponents with successive POST requests against a simple Tomcat 7 servlet (Form-based POST Authentication is enabled). After a sucessfull authentication, the client requests the same protected resource a few times in a row, but the second request always returns a "501 Method not implemented" status. All other requests succeed.

The following communication takes place:
1. Client requests a protected resource; Tomcat returns the login page (HTTP200)
2. Client provides the user credentials and calls the login resource; Tomcat returns a redirect (HTTP302)
3. Client sets the location from the redirect for the next request(identical to URI from #1) and requests it; Tomcat returns the page (HTTP200)
4. Client requests the same resource again; Tomcat returns a HTTP501 - Method not implemented
5. Client requests the same resource again; Tomcat returns the page (HTTP200)
6. Client requests the same resource again; Tomcat returns the page (HTTP200)
7. Client requests the same resource again; Tomcat returns the page (HTTP200)

The access log message regarding the 501 says:
'"testName=testValuePOST /test/secure/ HTTP/1.1" 501 1278', which may indicate that the entity data and the HTTP-method name somehow got mixed up!? Strangely the HTTP501 does not appear in case of a JSP for the requested resource, only if facing a form-based POST authentication Servlet. The servlet does only implement post and get(which calls the doPost) and returns just a string. The client code should be fine since I already posted this issue on the HTTPComponents mailing list and the data sent over the wire seems to be right. 

I attached the source/bin of the testclient and webapp and also the wire/context log of the client.

How can I provide further helpfull information?
Comment 1 hanswaehne 2010-08-19 05:53:00 UTC
also tested against Tomcat v6.0.29 with the same result and against Tomcat v5.5 (I think) which returns the correct return code HTTP 200, but threw internal exceptions.
Comment 2 Mark Thomas 2010-08-22 18:56:27 UTC
Thanks for the test case. As always, a simple ready to run test case makes diagnosis a lot easier.

The root cause is a difference between what the HTTP specs say and what user agents actually implemented with respect to handling 302 responses to POST requests. RFC2616 tried to deal with this by adding the 303 response. Your test case responds to the 302 with a POST (arguably in breach of the HTTP spec but it does depend how you read it) which Tomcat isn't expecting so due to request pipe-lining the POST data gets handled as part of the next request.

Tomcat's FORM authentication currently uses a 302 response for the redirect stage. A 303 would make the expected client behaviour clearer but that would only work for HTTP 1.1 clients. HTTP 1.0 clients would still be broken.

I therefore took the approach for Tomcat 7 of swallowing any request body sent in response to the redirect since Tomcat will restore the original request (the one made prior to the login form being received) including any request body provided at that time.

I am leaning towards not back-porting this change to Tomcat 5/6 since the implementation is consistent with the user agent behaviour.
Comment 3 Ed Saltelli 2011-07-20 21:25:01 UTC
One side-effect of consuming the Request's body is that consumers of the restored request are forced into using request.getInputStream() i.e. you cannot attempt to obtain a reader via request.getReader().
Comment 4 Konstantin Kolinko 2011-10-20 12:13:52 UTC
(In reply to comment #3)
> One side-effect of consuming the Request's body is that consumers of the
> restored request are forced into using request.getInputStream() i.e. you cannot
> attempt to obtain a reader via request.getReader().

https://issues.apache.org/bugzilla/show_bug.cgi?id=51940#c9

Should be fixed in 7.0.23 with r1186383 , but please check it.

Comments in FIXED bugs are usually lost. It is always better to REOPEN it if there are problems and the fix was done recently, or file a NEW bug if time has passed. As usual you'd better provide a scenario / sample webapp to reproduce it.