diff --git a/google-http-client-apache-v2/src/test/java/com/google/api/client/http/apache/v2/ApacheHttpTransportTest.java b/google-http-client-apache-v2/src/test/java/com/google/api/client/http/apache/v2/ApacheHttpTransportTest.java index 48a9d1c56..b01cfc47e 100644 --- a/google-http-client-apache-v2/src/test/java/com/google/api/client/http/apache/v2/ApacheHttpTransportTest.java +++ b/google-http-client-apache-v2/src/test/java/com/google/api/client/http/apache/v2/ApacheHttpTransportTest.java @@ -338,4 +338,38 @@ public void handle(HttpExchange httpExchange) throws IOException { private boolean isWindows() { return System.getProperty("os.name").startsWith("Windows"); } + + @Test(timeout = 10_000L) + public void testDisconnectShouldNotWaitToReadResponse() throws IOException { + // This handler waits for 100s before returning writing content. The test should + // timeout if disconnect waits for the response before closing the connection. + final HttpHandler handler = + new HttpHandler() { + @Override + public void handle(HttpExchange httpExchange) throws IOException { + byte[] response = httpExchange.getRequestURI().toString().getBytes(); + httpExchange.sendResponseHeaders(200, response.length); + + // Sleep for longer than the test timeout + try { + Thread.sleep(100_000); + } catch (InterruptedException e) { + throw new IOException("interrupted", e); + } + try (OutputStream out = httpExchange.getResponseBody()) { + out.write(response); + } + } + }; + + try (FakeServer server = new FakeServer(handler)) { + HttpTransport transport = new ApacheHttpTransport(); + GenericUrl testUrl = new GenericUrl("http://localhost/foo//bar"); + testUrl.setPort(server.getPort()); + com.google.api.client.http.HttpResponse response = + transport.createRequestFactory().buildGetRequest(testUrl).execute(); + // disconnect should not wait to read the entire content + response.disconnect(); + } + } } diff --git a/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java b/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java index 130208671..7f75bccd6 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java +++ b/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java @@ -438,11 +438,20 @@ public void ignore() throws IOException { * Disconnect using {@link LowLevelHttpResponse#disconnect()}, then close the HTTP response * content using {@link #ignore}. * + *
The underlying connection is aborted first so that closing the response content in {@link + * #ignore} does not block to drain remaining response bytes (e.g. when only a small prefix of a + * large response was read). Any {@link IOException} from {@link #ignore} after an abort is + * expected and silently swallowed. + * * @since 1.4 */ public void disconnect() throws IOException { - ignore(); response.disconnect(); + try { + ignore(); + } catch (IOException e) { + // Expected when the connection was aborted before content was fully consumed. + } } /**