[
https://issues.apache.org/jira/browse/HTTPCLIENT-1376?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13688121#comment-13688121
]
Carl D'Halluin commented on HTTPCLIENT-1376:
--------------------------------------------
// Java client source code:
package com.amplidata.csg.backend;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class HTTP11Test {
private final static String HOST = "127.0.0.1";
private final static int PORT = 8777;
private static String doRequest(final HttpClient client, boolean
expectAuthentication, boolean processBody)
throws ClientProtocolException, IOException {
final String url = "http://" + HOST + ":" + PORT + "/"
+ (expectAuthentication ? "authenticated.html" :
"non-authenticated.html");
System.out.println("\nREQUEST: GET " + url);
final HttpResponse resp = client.execute(new HttpGet(url));
final String statusLine = resp.getStatusLine().toString();
System.out.println("RESPONSE STATUS: " + statusLine);
if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
System.out.println("--> BUG! Response status " +
resp.getStatusLine().getStatusCode());
if (processBody) {
final BufferedReader br = new BufferedReader(new
InputStreamReader(resp.getEntity().getContent()));
String line;
while ((line = br.readLine()) != null) {
System.out.println("RESPONSE BODY: " + line);
}
} else {
EntityUtils.consumeQuietly(resp.getEntity());
System.out.println("RESPONSE BODY - SKIPPED");
}
return statusLine;
}
private static void printLine() {
System.out.println("\n=======================");
}
public static void main(String[] args) throws ClientProtocolException,
IOException {
final DefaultHttpClient client = new DefaultHttpClient();
client.getCredentialsProvider().setCredentials(new AuthScope(HOST,
PORT),
new UsernamePasswordCredentials("user", "pass"));
boolean authenticated;
boolean processBodyExplicitly;
// No authentication; no explicit reading of response body.
// The HTTP/1.1 connection is not reused, which is correct
authenticated = false;
processBodyExplicitly = false;
doRequest(client, authenticated, processBodyExplicitly);
doRequest(client, authenticated, processBodyExplicitly);
printLine();
// No authentication; with explicit reading & logging of response body.
// The HTTP/1.1 connection is not reused, which is correct
authenticated = false;
processBodyExplicitly = true;
doRequest(client, authenticated, processBodyExplicitly);
doRequest(client, authenticated, processBodyExplicitly);
printLine();
// Authentication; with explicit reading & logging of response body.
// The HTTP/1.1 connection is not reused, which is correct
authenticated = true;
processBodyExplicitly = true;
doRequest(client, authenticated, processBodyExplicitly);
doRequest(client, authenticated, processBodyExplicitly);
printLine();
// Authentication; no explicit reading of response body.
// The HTTP/1.1 connection IS REUSED, which is NOT correct
// The body of the first response is used as a response for the second
request
authenticated = true;
processBodyExplicitly = false;
doRequest(client, authenticated, processBodyExplicitly);
doRequest(client, authenticated, processBodyExplicitly); // BUG: we get
a 400 response but should get a 200
}
}
> 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
> 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: [email protected]
For additional commands, e-mail: [email protected]