diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java index a7fe5f19e02..20120aad7d5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package jdk.internal.net.http; +import java.io.IOError; import java.io.IOException; import java.lang.ref.WeakReference; import java.net.ConnectException; @@ -440,7 +441,9 @@ class MultiExchange implements Cancelable { try { // 3. apply response filters newrequest = responseFilters(response); - } catch (IOException e) { + } catch (Throwable t) { + IOException e = t instanceof IOException io ? io : new IOException(t); + exch.exchImpl.cancel(e); return failedFuture(e); } // 4. check filter result and repeat or continue diff --git a/test/jdk/java/net/httpclient/UnauthorizedTest.java b/test/jdk/java/net/httpclient/UnauthorizedTest.java index 389a79761dd..e2124f2a7ed 100644 --- a/test/jdk/java/net/httpclient/UnauthorizedTest.java +++ b/test/jdk/java/net/httpclient/UnauthorizedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8203882 + * @bug 8203882 8352623 * @summary (httpclient) Check that HttpClient throws IOException when * receiving 401/407 with no WWW-Authenticate/Proxy-Authenticate * header only in the case where an authenticator is configured @@ -36,9 +36,6 @@ * UnauthorizedTest */ -import com.sun.net.httpserver.HttpServer; -import com.sun.net.httpserver.HttpsConfigurator; -import com.sun.net.httpserver.HttpsServer; import jdk.test.lib.net.SimpleSSLContext; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; @@ -49,9 +46,8 @@ import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.ref.WeakReference; import java.net.Authenticator; -import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; @@ -60,7 +56,6 @@ import java.net.http.HttpResponse.BodyHandlers; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicLong; import jdk.httpclient.test.lib.common.HttpServerAdapters; -import jdk.httpclient.test.lib.http2.Http2TestServer; import static java.lang.System.out; import static java.net.http.HttpClient.Version.HTTP_1_1; @@ -95,41 +90,45 @@ public class UnauthorizedTest implements HttpServerAdapters { static final int HTTP_OK = 200; static final String MESSAGE = "Unauthorized"; + static WeakReference ref(HttpClient client) { + return new WeakReference<>(client); + } + @DataProvider(name = "all") public Object[][] positive() { return new Object[][] { - { httpURI + "/server", UNAUTHORIZED, true, authClient}, - { httpsURI + "/server", UNAUTHORIZED, true, authClient}, - { http2URI + "/server", UNAUTHORIZED, true, authClient}, - { https2URI + "/server", UNAUTHORIZED, true, authClient}, - { httpURI + "/proxy", PROXY_UNAUTHORIZED, true, authClient}, - { httpsURI + "/proxy", PROXY_UNAUTHORIZED, true, authClient}, - { http2URI + "/proxy", PROXY_UNAUTHORIZED, true, authClient}, - { https2URI + "/proxy", PROXY_UNAUTHORIZED, true, authClient}, - { httpURI + "/server", UNAUTHORIZED, false, authClient}, - { httpsURI + "/server", UNAUTHORIZED, false, authClient}, - { http2URI + "/server", UNAUTHORIZED, false, authClient}, - { https2URI + "/server", UNAUTHORIZED, false, authClient}, - { httpURI + "/proxy", PROXY_UNAUTHORIZED, false, authClient}, - { httpsURI + "/proxy", PROXY_UNAUTHORIZED, false, authClient}, - { http2URI + "/proxy", PROXY_UNAUTHORIZED, false, authClient}, - { https2URI + "/proxy", PROXY_UNAUTHORIZED, false, authClient}, - { httpURI + "/server", UNAUTHORIZED, true, noAuthClient}, - { httpsURI + "/server", UNAUTHORIZED, true, noAuthClient}, - { http2URI + "/server", UNAUTHORIZED, true, noAuthClient}, - { https2URI + "/server", UNAUTHORIZED, true, noAuthClient}, - { httpURI + "/proxy", PROXY_UNAUTHORIZED, true, noAuthClient}, - { httpsURI + "/proxy", PROXY_UNAUTHORIZED, true, noAuthClient}, - { http2URI + "/proxy", PROXY_UNAUTHORIZED, true, noAuthClient}, - { https2URI + "/proxy", PROXY_UNAUTHORIZED, true, noAuthClient}, - { httpURI + "/server", UNAUTHORIZED, false, noAuthClient}, - { httpsURI + "/server", UNAUTHORIZED, false, noAuthClient}, - { http2URI + "/server", UNAUTHORIZED, false, noAuthClient}, - { https2URI + "/server", UNAUTHORIZED, false, noAuthClient}, - { httpURI + "/proxy", PROXY_UNAUTHORIZED, false, noAuthClient}, - { httpsURI + "/proxy", PROXY_UNAUTHORIZED, false, noAuthClient}, - { http2URI + "/proxy", PROXY_UNAUTHORIZED, false, noAuthClient}, - { https2URI + "/proxy", PROXY_UNAUTHORIZED, false, noAuthClient}, + { httpURI + "/server", UNAUTHORIZED, true, ref(authClient)}, + { httpsURI + "/server", UNAUTHORIZED, true, ref(authClient)}, + { http2URI + "/server", UNAUTHORIZED, true, ref(authClient)}, + { https2URI + "/server", UNAUTHORIZED, true, ref(authClient)}, + { httpURI + "/proxy", PROXY_UNAUTHORIZED, true, ref(authClient)}, + { httpsURI + "/proxy", PROXY_UNAUTHORIZED, true, ref(authClient)}, + { http2URI + "/proxy", PROXY_UNAUTHORIZED, true, ref(authClient)}, + { https2URI + "/proxy", PROXY_UNAUTHORIZED, true, ref(authClient)}, + { httpURI + "/server", UNAUTHORIZED, false, ref(authClient)}, + { httpsURI + "/server", UNAUTHORIZED, false, ref(authClient)}, + { http2URI + "/server", UNAUTHORIZED, false, ref(authClient)}, + { https2URI + "/server", UNAUTHORIZED, false, ref(authClient)}, + { httpURI + "/proxy", PROXY_UNAUTHORIZED, false, ref(authClient)}, + { httpsURI + "/proxy", PROXY_UNAUTHORIZED, false, ref(authClient)}, + { http2URI + "/proxy", PROXY_UNAUTHORIZED, false, ref(authClient)}, + { https2URI + "/proxy", PROXY_UNAUTHORIZED, false, ref(authClient)}, + { httpURI + "/server", UNAUTHORIZED, true, ref(noAuthClient)}, + { httpsURI + "/server", UNAUTHORIZED, true, ref(noAuthClient)}, + { http2URI + "/server", UNAUTHORIZED, true, ref(noAuthClient)}, + { https2URI + "/server", UNAUTHORIZED, true, ref(noAuthClient)}, + { httpURI + "/proxy", PROXY_UNAUTHORIZED, true, ref(noAuthClient)}, + { httpsURI + "/proxy", PROXY_UNAUTHORIZED, true, ref(noAuthClient)}, + { http2URI + "/proxy", PROXY_UNAUTHORIZED, true, ref(noAuthClient)}, + { https2URI + "/proxy", PROXY_UNAUTHORIZED, true, ref(noAuthClient)}, + { httpURI + "/server", UNAUTHORIZED, false, ref(noAuthClient)}, + { httpsURI + "/server", UNAUTHORIZED, false, ref(noAuthClient)}, + { http2URI + "/server", UNAUTHORIZED, false, ref(noAuthClient)}, + { https2URI + "/server", UNAUTHORIZED, false, ref(noAuthClient)}, + { httpURI + "/proxy", PROXY_UNAUTHORIZED, false, ref(noAuthClient)}, + { httpsURI + "/proxy", PROXY_UNAUTHORIZED, false, ref(noAuthClient)}, + { http2URI + "/proxy", PROXY_UNAUTHORIZED, false, ref(noAuthClient)}, + { https2URI + "/proxy", PROXY_UNAUTHORIZED, false, ref(noAuthClient)}, }; } @@ -139,7 +138,8 @@ public class UnauthorizedTest implements HttpServerAdapters { }; @Test(dataProvider = "all") - void test(String uriString, int code, boolean async, HttpClient client) throws Throwable { + void test(String uriString, int code, boolean async, WeakReference clientRef) throws Throwable { + HttpClient client = clientRef.get(); out.printf("%n---- starting (%s, %d, %s, %s) ----%n", uriString, code, async ? "async" : "sync", client.authenticator().isPresent() ? "authClient" : "noAuthClient"); @@ -223,10 +223,20 @@ public class UnauthorizedTest implements HttpServerAdapters { @AfterTest public void teardown() throws Exception { + // authClient.close(); + // noAuthClient.close(); + var TRACKER = ReferenceTracker.INSTANCE; + TRACKER.track(authClient); + TRACKER.track(noAuthClient); + authClient = noAuthClient = null; + System.gc(); + var error = TRACKER.check(1000); + httpTestServer.stop(); httpsTestServer.stop(); http2TestServer.stop(); https2TestServer.stop(); + if (error != null) throw error; } static class UnauthorizedHandler implements HttpTestHandler {