From e8c5d1bca41ca474379363f4c9a188de3073a8f7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 13 Apr 2013 10:38:24 +0000 Subject: [PATCH] Backported fix and test case for HTTPCLIENT-1340 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1467586 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/conn/BasicManagedEntity.java | 40 ++++++++++------- .../integration/TestClientAuthentication.java | 45 +++++++++++++++++++ 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/BasicManagedEntity.java b/httpclient/src/main/java/org/apache/http/conn/BasicManagedEntity.java index f39f0d507..ecd4f6baa 100644 --- a/httpclient/src/main/java/org/apache/http/conn/BasicManagedEntity.java +++ b/httpclient/src/main/java/org/apache/http/conn/BasicManagedEntity.java @@ -97,6 +97,8 @@ private void ensureConsumed() throws IOException { // this will not trigger a callback from EofSensorInputStream EntityUtils.consume(wrappedEntity); managedConn.markReusable(); + } else { + managedConn.unmarkReusable(); } } finally { releaseManagedConnection(); @@ -135,11 +137,15 @@ public void abortConnection() throws IOException { public boolean eofDetected(final InputStream wrapped) throws IOException { try { - if (attemptReuse && (managedConn != null)) { - // there may be some cleanup required, such as - // reading trailers after the response body: - wrapped.close(); - managedConn.markReusable(); + if (managedConn != null) { + if (attemptReuse) { + // there may be some cleanup required, such as + // reading trailers after the response body: + wrapped.close(); + managedConn.markReusable(); + } else { + managedConn.unmarkReusable(); + } } } finally { releaseManagedConnection(); @@ -149,17 +155,21 @@ public boolean eofDetected(final InputStream wrapped) throws IOException { public boolean streamClosed(final InputStream wrapped) throws IOException { try { - if (attemptReuse && (managedConn != null)) { - final boolean valid = managedConn.isOpen(); - // this assumes that closing the stream will - // consume the remainder of the response body: - try { - wrapped.close(); - managedConn.markReusable(); - } catch (final SocketException ex) { - if (valid) { - throw ex; + if (managedConn != null) { + if (attemptReuse) { + final boolean valid = managedConn.isOpen(); + // this assumes that closing the stream will + // consume the remainder of the response body: + try { + wrapped.close(); + managedConn.markReusable(); + } catch (final SocketException ex) { + if (valid) { + throw ex; + } } + } else { + managedConn.unmarkReusable(); } } } finally { diff --git a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientAuthentication.java b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientAuthentication.java index a9fb2143b..2c66d0aa7 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientAuthentication.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientAuthentication.java @@ -60,6 +60,7 @@ import org.apache.http.localserver.LocalTestServer; import org.apache.http.localserver.RequestBasicAuth; import org.apache.http.localserver.ResponseBasicUnauthorized; +import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpExpectationVerifier; import org.apache.http.protocol.HttpProcessor; @@ -547,4 +548,48 @@ public void testAuthenticationTargetAsProxy() throws Exception { EntityUtils.consume(entity); } + static class ClosingAuthHandler implements HttpRequestHandler { + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + final String creds = (String) context.getAttribute("creds"); + if (creds == null || !creds.equals("test:test")) { + response.setStatusCode(HttpStatus.SC_UNAUTHORIZED); + } else { + response.setStatusCode(HttpStatus.SC_OK); + final StringEntity entity = new StringEntity("success", Consts.ASCII); + response.setEntity(entity); + response.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE); + } + } + + } + + @Test + public void testConnectionCloseAfterAuthenticationSuccess() throws Exception { + this.localServer.register("*", new ClosingAuthHandler()); + + final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials("test", "test")); + + this.httpclient = HttpClients.custom() + .setDefaultCredentialsProvider(credsProvider) + .build(); + + final HttpClientContext context = HttpClientContext.create(); + + final HttpHost targethost = getServerHttp(); + + for (int i = 0; i < 2; i++) { + final HttpGet httpget = new HttpGet("/"); + + final HttpResponse response = this.httpclient.execute(targethost, httpget, context); + EntityUtils.consume(response.getEntity()); + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + } + } + }