diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java index 27f38bd2e30a5..d7222067f7ee8 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java @@ -331,7 +331,7 @@ public CompletableFuture readBody(HttpResponse.BodySubscriber p, ); if (cf.isCompletedExceptionally()) { // if an error occurs during subscription - connection.close(cf.exceptionNow()); + connection.close(Utils.exceptionNow(cf)); return; } // increment the reference count on the HttpClientImpl diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index 511b17d7813cb..d035a8c8da1cf 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -57,6 +57,7 @@ import java.util.List; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ConcurrentHashMap; @@ -1133,4 +1134,31 @@ public static String encode(String s) { } return sb.toString(); } + + /** + * {@return the exception the given {@code cf} was completed with, + * or a {@link CancellationException} if the given {@code cf} was + * cancelled} + * + * @param cf a {@code CompletableFuture} exceptionally completed + * @throws IllegalArgumentException if the given cf was not + * {@linkplain CompletableFuture#isCompletedExceptionally() + * completed exceptionally} + */ + public static Throwable exceptionNow(CompletableFuture cf) { + if (cf.isCompletedExceptionally()) { + if (cf.isCancelled()) { + try { + cf.join(); + } catch (CancellationException x) { + return x; + } catch (CompletionException x) { + return x.getCause(); + } + } else { + return cf.exceptionNow(); + } + } + throw new IllegalArgumentException("cf is not completed exceptionally"); + } } diff --git a/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java b/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java index a2b6af8a88878..5d09c01b96fc8 100644 --- a/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java +++ b/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java @@ -93,17 +93,20 @@ public void test(URI uri) { err.printf("\nTesting with Version: %s, URI: %s\n", HTTP_2, uri.toASCIIString()); Iterable iterable = EndlessDataChunks::new; HttpRequest.BodyPublisher testPub = HttpRequest.BodyPublishers.ofByteArrays(iterable); - Exception exception = null; - Throwable testThrowable = null; + Exception expectedException = null; try { performRequest(testPub, uri); + throw new AssertionError("Expected exception not raised for " + uri); } catch (Exception e) { - exception = e; - testThrowable = e.getCause(); + expectedException = e; } - assertNotNull(exception, "Request should have completed exceptionally but exception is null"); - assertNotNull(testThrowable, "Request should have completed exceptionally but testThrowable is null"); - assertEquals(testThrowable.getClass(), IOException.class, "Test should have closed with an IOException"); + Throwable testThrowable = expectedException.getCause(); + if (testThrowable == null) { + throw new AssertionError("Unexpected null cause for " + expectedException, + expectedException); + } + assertEquals(testThrowable.getClass(), IOException.class, + "Test should have closed with an IOException"); testThrowable.printStackTrace(); }