hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Carl D'Halluin (JIRA)" <j...@apache.org>
Subject [jira] [Updated] (HTTPCLIENT-1376) HttpClient incorrectly reuses HTTP/1.1 connection - the response body of the first request is considered as the response for the second request
Date Wed, 19 Jun 2013 16:27:20 GMT

     [ https://issues.apache.org/jira/browse/HTTPCLIENT-1376?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Carl D'Halluin updated HTTPCLIENT-1376:
---------------------------------------

    Description: 
In the following scenario, the HttpClient incorrectly reuses the HTTP/1.1 stream, and actually
considers the response body of the first request, to be the HTTP response to a second request.

Details:

1. Client does a simple HTTP/1.1 GET request
2. Server responds with a 401 and a WWW-Authenticate header
3. Client repeats the GET request but now with an Authorization header
4. Server responds with a HTTP/1.1 200 OK but there is no content length. The server sends
a response body
5. HttpClient ignores the response body by closing the entity content InputStream (or call
EntityUtils.consume)
6. Client sends a new HTTP/1.1 GET request (totally unrelated to the previous one)
7. Client erroneously considers the response body received in step 5 as the response to step
6

I tracked the bug down in the HttpClient library: Step 2 marks the HTTP connection as reusable.
Step 4 should explicitly mark the connection as non-reusable since the only thing the client
can do to such an ugly reponse (no content-length) is read until EOF. However, that does not
happen in step 4. Hence in step 5 the code sees that the connection is reusable, and doesnt
bother consuming the response content at all. The body is reused in step 7

Here we see 4 times 2 subsequent request
- first 2 are no authentication no streaming: HttpClient correctly does not reuse connection
(see port number)
- next 2 are no authentication with streaming: HttpClient correctly does not reuse connection
- next 2 are with authentication with streaming: HttpClient correctly does not reuse connection
- final 2 are with authentication no streaming: Bug - HttpClient tries to reuse connection
given error. Closing the HttpResponse InputStream does not correctly close the underlying
Socket

{code}
REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49603
RESPONSE BODY - SKIPPED

REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49604
RESPONSE BODY - SKIPPED

=======================

REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49605
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49605
RESPONSE BODY:   

REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49606
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49606
RESPONSE BODY:   

=======================

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49607
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49607
RESPONSE BODY:   

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49608
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49608
RESPONSE BODY:   

=======================

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49609
RESPONSE BODY - SKIPPED

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 400 This is a request body - client is 127.0.0.1:49609
--> BUG! Response status 400
RESPONSE BODY - SKIPPED
{code}



  was:
In the following scenario, the HttpClient incorrectly reuses the HTTP/1.1 stream, and actually
considers the response body of the first request, to be the HTTP response to a second request.

Details:

1. Client does a simple HTTP/1.1 GET request
2. Server responds with a 401 and a WWW-Authenticate header
3. Client repeats the GET request but now with an Authorization header
4. Server responds with a HTTP/1.1 200 OK but there is no content length. The server sends
a response body
5. HttpClient ignores the response body by closing the entity content InputStream (or call
EntityUtils.consume)
6. Client sends a new HTTP/1.1 GET request (totally unrelated to the previous one)
7. Client erroneously considers the response body received in step 5 as the response to step
6

Step 2 marks the HTTP connection as reusable. Step 4 should explicitly mark the connection
as non-reusable since the only thing the client can do to such an ugly reponse (no content-length)
is read until EOF. However, that does not happen in step 4. Hence in step 5 the code sees
that the connection is reusable, and doesnt bother consuming the response content at all.
The body is reused in step 7

Here we see 4 times 2 subsequent request
- first 2 are no authentication no streaming: HttpClient correctly does not reuse connection
(see port number)
- next 2 are no authentication with streaming: HttpClient correctly does not reuse connection
- next 2 are with authentication with streaming: HttpClient correctly does not reuse connection
- final 2 are with authentication no streaming: Bug - HttpClient tries to reuse connection
given error. Closing the HttpResponse InputStream does not correctly close the underlying
Socket

{code}
REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49603
RESPONSE BODY - SKIPPED

REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49604
RESPONSE BODY - SKIPPED

=======================

REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49605
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49605
RESPONSE BODY:   

REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49606
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49606
RESPONSE BODY:   

=======================

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49607
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49607
RESPONSE BODY:   

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49608
RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49608
RESPONSE BODY:   

=======================

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49609
RESPONSE BODY - SKIPPED

REQUEST: GET http://127.0.0.1:8777/authenticated.html
RESPONSE STATUS: HTTP/1.1 400 This is a request body - client is 127.0.0.1:49609
--> BUG! Response status 400
RESPONSE BODY - SKIPPED
{code}



    
> HttpClient incorrectly reuses HTTP/1.1 connection - the response body of the first request
is considered as the response for the second request
> -----------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-1376
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-1376
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>    Affects Versions: 4.2.4
>            Reporter: Carl D'Halluin
>
> In the following scenario, the HttpClient incorrectly reuses the HTTP/1.1 stream, and
actually considers the response body of the first request, to be the HTTP response to a second
request.
> Details:
> 1. Client does a simple HTTP/1.1 GET request
> 2. Server responds with a 401 and a WWW-Authenticate header
> 3. Client repeats the GET request but now with an Authorization header
> 4. Server responds with a HTTP/1.1 200 OK but there is no content length. The server
sends a response body
> 5. HttpClient ignores the response body by closing the entity content InputStream (or
call EntityUtils.consume)
> 6. Client sends a new HTTP/1.1 GET request (totally unrelated to the previous one)
> 7. Client erroneously considers the response body received in step 5 as the response
to step 6
> I tracked the bug down in the HttpClient library: Step 2 marks the HTTP connection as
reusable. Step 4 should explicitly mark the connection as non-reusable since the only thing
the client can do to such an ugly reponse (no content-length) is read until EOF. However,
that does not happen in step 4. Hence in step 5 the code sees that the connection is reusable,
and doesnt bother consuming the response content at all. The body is reused in step 7
> Here we see 4 times 2 subsequent request
> - first 2 are no authentication no streaming: HttpClient correctly does not reuse connection
(see port number)
> - next 2 are no authentication with streaming: HttpClient correctly does not reuse connection
> - next 2 are with authentication with streaming: HttpClient correctly does not reuse
connection
> - final 2 are with authentication no streaming: Bug - HttpClient tries to reuse connection
given error. Closing the HttpResponse InputStream does not correctly close the underlying
Socket
> {code}
> REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
> RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49603
> RESPONSE BODY - SKIPPED
> REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
> RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49604
> RESPONSE BODY - SKIPPED
> =======================
> REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
> RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49605
> RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49605
> RESPONSE BODY:   
> REQUEST: GET http://127.0.0.1:8777/non-authenticated.html
> RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49606
> RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49606
> RESPONSE BODY:   
> =======================
> REQUEST: GET http://127.0.0.1:8777/authenticated.html
> RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49607
> RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49607
> RESPONSE BODY:   
> REQUEST: GET http://127.0.0.1:8777/authenticated.html
> RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49608
> RESPONSE BODY:   HTTP/1.1 400 This is a request body - client is 127.0.0.1:49608
> RESPONSE BODY:   
> =======================
> REQUEST: GET http://127.0.0.1:8777/authenticated.html
> RESPONSE STATUS: HTTP/1.1 200 OK - client is 127.0.0.1:49609
> RESPONSE BODY - SKIPPED
> REQUEST: GET http://127.0.0.1:8777/authenticated.html
> RESPONSE STATUS: HTTP/1.1 400 This is a request body - client is 127.0.0.1:49609
> --> BUG! Response status 400
> RESPONSE BODY - SKIPPED
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Mime
View raw message