Skip to content

Commit e1f1a11

Browse files
Alexey BakhtinRealCLanger
authored andcommitted
8345625: Better HTTP connections
Reviewed-by: mbalao, andrew Backport-of: 2ad3d59e4eb8882ee46a70c70cc75c9c0d008211
1 parent bb83d59 commit e1f1a11

File tree

9 files changed

+112
-45
lines changed

9 files changed

+112
-45
lines changed

src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,6 @@
2424
*/
2525
package sun.net.ftp.impl;
2626

27-
28-
2927
import java.io.BufferedInputStream;
3028
import java.io.BufferedOutputStream;
3129
import java.io.BufferedReader;
@@ -64,13 +62,15 @@
6462
import java.util.regex.Pattern;
6563
import javax.net.ssl.SSLSocket;
6664
import javax.net.ssl.SSLSocketFactory;
65+
6766
import sun.net.ftp.FtpDirEntry;
6867
import sun.net.ftp.FtpDirParser;
6968
import sun.net.ftp.FtpProtocolException;
7069
import sun.net.ftp.FtpReplyCode;
7170
import sun.net.util.IPAddressUtil;
7271
import sun.util.logging.PlatformLogger;
7372

73+
import static sun.net.util.ProxyUtil.copyProxy;
7474

7575
public class FtpClient extends sun.net.ftp.FtpClient {
7676

@@ -982,7 +982,7 @@ public int getReadTimeout() {
982982
}
983983

984984
public sun.net.ftp.FtpClient setProxy(Proxy p) {
985-
proxy = p;
985+
proxy = copyProxy(p);
986986
return this;
987987
}
988988

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package sun.net.util;
27+
28+
import sun.net.ApplicationProxy;
29+
30+
import java.net.Proxy;
31+
32+
public final class ProxyUtil {
33+
34+
private ProxyUtil() {}
35+
36+
/**
37+
* Creates a new {@link Proxy} instance for the given proxy iff it is
38+
* neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, an
39+
* {@link ApplicationProxy} instance, nor already a {@code Proxy} instance.
40+
*/
41+
public static Proxy copyProxy(Proxy proxy) {
42+
return proxy == null
43+
|| proxy.getClass() == Proxy.class
44+
|| proxy instanceof ApplicationProxy
45+
? proxy
46+
: new Proxy(proxy.type(), proxy.address());
47+
}
48+
49+
}

src/java.base/share/classes/sun/net/www/http/HttpClient.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,8 @@
4141
import sun.net.www.protocol.http.AuthCacheImpl;
4242
import sun.net.www.protocol.http.HttpURLConnection;
4343
import sun.util.logging.PlatformLogger;
44+
45+
import static sun.net.util.ProxyUtil.copyProxy;
4446
import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
4547
import sun.security.action.GetPropertyAction;
4648

@@ -267,7 +269,7 @@ public HttpClient(URL url, String proxyHost, int proxyPort)
267269
}
268270

269271
protected HttpClient(URL url, Proxy p, int to) throws IOException {
270-
proxy = (p == null) ? Proxy.NO_PROXY : p;
272+
proxy = p == null ? Proxy.NO_PROXY : copyProxy(p);
271273
this.host = url.getHost();
272274
this.url = url;
273275
port = url.getPort();
@@ -332,9 +334,7 @@ public static HttpClient New(URL url, boolean useCache)
332334
public static HttpClient New(URL url, Proxy p, int to, boolean useCache,
333335
HttpURLConnection httpuc) throws IOException
334336
{
335-
if (p == null) {
336-
p = Proxy.NO_PROXY;
337-
}
337+
p = p == null ? Proxy.NO_PROXY : copyProxy(p);
338338
HttpClient ret = null;
339339
/* see if one's already around */
340340
if (useCache) {

src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@
4848
import java.util.StringTokenizer;
4949
import java.security.Permission;
5050
import java.util.Properties;
51+
5152
import sun.net.NetworkClient;
5253
import sun.net.util.IPAddressUtil;
5354
import sun.net.www.MessageHeader;
@@ -59,6 +60,7 @@
5960
import sun.net.www.ParseUtil;
6061
import sun.security.action.GetPropertyAction;
6162

63+
import static sun.net.util.ProxyUtil.copyProxy;
6264

6365
/**
6466
* This class Opens an FTP input (or output) stream given a URL.
@@ -246,7 +248,7 @@ public ProxySelector run() {
246248
throw new IOException("Failed to select a proxy", iae);
247249
}
248250
for (Proxy proxy : proxies) {
249-
p = proxy;
251+
p = copyProxy(proxy);
250252
if (p == null || p == Proxy.NO_PROXY ||
251253
p.type() == Proxy.Type.SOCKS) {
252254
break;

src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -33,11 +33,9 @@
3333
import java.net.MalformedURLException;
3434
import java.net.URL;
3535
import java.net.Proxy;
36-
import java.util.Map;
37-
import java.util.HashMap;
3836
import java.util.Objects;
39-
import sun.net.ftp.FtpClient;
40-
import sun.net.www.protocol.http.HttpURLConnection;
37+
38+
import static sun.net.util.ProxyUtil.copyProxy;
4139

4240
/** open an ftp connection given a URL */
4341
public class Handler extends java.net.URLStreamHandler {
@@ -57,11 +55,11 @@ protected java.net.URLConnection openConnection(URL u)
5755
return openConnection(u, null);
5856
}
5957

60-
protected java.net.URLConnection openConnection(URL u, Proxy p)
58+
protected java.net.URLConnection openConnection(URL u, Proxy proxy)
6159
throws IOException {
62-
FtpURLConnection connection = null;
60+
FtpURLConnection connection;
6361
try {
64-
connection = new FtpURLConnection(u, p);
62+
connection = new FtpURLConnection(u, copyProxy(proxy));
6563
} catch (IllegalArgumentException e) {
6664
var mfue = new MalformedURLException(e.getMessage());
6765
mfue.initCause(e);

src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -84,6 +84,7 @@
8484
import java.util.Properties;
8585
import java.util.concurrent.locks.ReentrantLock;
8686

87+
import static sun.net.util.ProxyUtil.copyProxy;
8788
import static sun.net.www.protocol.http.AuthScheme.BASIC;
8889
import static sun.net.www.protocol.http.AuthScheme.DIGEST;
8990
import static sun.net.www.protocol.http.AuthScheme.NTLM;
@@ -931,7 +932,7 @@ protected HttpURLConnection(URL u, Proxy p, Handler handler)
931932
responses = new MessageHeader(maxHeaderSize);
932933
userHeaders = new MessageHeader();
933934
this.handler = handler;
934-
instProxy = p;
935+
instProxy = copyProxy(p);
935936
if (instProxy instanceof sun.net.ApplicationProxy) {
936937
/* Application set Proxies should not have access to cookies
937938
* in a secure environment unless explicitly allowed. */
@@ -1246,7 +1247,7 @@ public ProxySelector run() {
12461247
final Iterator<Proxy> it = proxies.iterator();
12471248
Proxy p;
12481249
while (it.hasNext()) {
1249-
p = it.next();
1250+
p = copyProxy(it.next());
12501251
try {
12511252
if (!failedOnce) {
12521253
http = getNewHttpClient(url, p, connectTimeout);

src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@
4848

4949
import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
5050
import static jdk.internal.net.http.common.Utils.ProxyHeaders;
51+
import static jdk.internal.net.http.common.Utils.copyProxy;
5152

5253
public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
5354

@@ -128,15 +129,7 @@ public HttpRequestImpl(HttpRequest request, ProxySelector ps) {
128129
this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
129130
}
130131
this.uri = requestURI;
131-
if (isWebSocket) {
132-
// WebSocket determines and sets the proxy itself
133-
this.proxy = ((HttpRequestImpl) request).proxy;
134-
} else {
135-
if (ps != null)
136-
this.proxy = retrieveProxy(ps, uri);
137-
else
138-
this.proxy = null;
139-
}
132+
this.proxy = retrieveProxy(request, ps, uri);
140133
this.expectContinue = request.expectContinue();
141134
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
142135
this.requestPublisher = request.bodyPublisher().orElse(null);
@@ -295,16 +288,27 @@ void setH2Upgrade(Exchange<?> exchange) {
295288
@Override
296289
public boolean expectContinue() { return expectContinue; }
297290

298-
/** Retrieves the proxy, from the given ProxySelector, if there is one. */
299-
private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
300-
Proxy proxy = null;
301-
List<Proxy> pl = ps.select(uri);
302-
if (!pl.isEmpty()) {
303-
Proxy p = pl.get(0);
304-
if (p.type() == Proxy.Type.HTTP)
305-
proxy = p;
291+
/** Retrieves a copy of the proxy either from the given {@link HttpRequest} or {@link ProxySelector}, if there is one. */
292+
private static Proxy retrieveProxy(HttpRequest request, ProxySelector ps, URI uri) {
293+
294+
// WebSocket determines and sets the proxy itself
295+
if (request instanceof HttpRequestImpl requestImpl && requestImpl.isWebSocket) {
296+
return requestImpl.proxy;
297+
}
298+
299+
// Try to find a matching one from the `ProxySelector`
300+
if (ps != null) {
301+
List<Proxy> pl = ps.select(uri);
302+
if (!pl.isEmpty()) {
303+
Proxy p = pl.getFirst();
304+
if (p.type() == Proxy.Type.HTTP) {
305+
return copyProxy(p);
306+
}
307+
}
306308
}
307-
return proxy;
309+
310+
return null;
311+
308312
}
309313

310314
InetSocketAddress proxy() {
@@ -320,7 +324,7 @@ InetSocketAddress proxy() {
320324
@Override
321325
public void setProxy(Proxy proxy) {
322326
assert isWebSocket;
323-
this.proxy = proxy;
327+
this.proxy = copyProxy(proxy);
324328
}
325329

326330
@Override

src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
3838
import java.lang.System.Logger.Level;
3939
import java.net.ConnectException;
4040
import java.net.InetSocketAddress;
41+
import java.net.Proxy;
4142
import java.net.URI;
4243
import java.net.URLPermission;
4344
import java.net.http.HttpClient;
@@ -313,6 +314,17 @@ public static boolean proxyHasDisabledSchemes(boolean tunnel) {
313314
: ! PROXY_AUTH_DISABLED_SCHEMES.isEmpty();
314315
}
315316

317+
/**
318+
* Creates a new {@link Proxy} instance for the given proxy iff it is
319+
* neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, nor already a
320+
* {@code Proxy} instance.
321+
*/
322+
public static Proxy copyProxy(Proxy proxy) {
323+
return proxy == null || proxy.getClass() == Proxy.class
324+
? proxy
325+
: new Proxy(proxy.type(), proxy.address());
326+
}
327+
316328
// WebSocket connection Upgrade headers
317329
private static final String HEADER_CONNECTION = "Connection";
318330
private static final String HEADER_UPGRADE = "Upgrade";

src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -64,6 +64,7 @@
6464
import java.util.stream.Stream;
6565

6666
import static java.lang.String.format;
67+
import static jdk.internal.net.http.common.Utils.copyProxy;
6768
import static jdk.internal.net.http.common.Utils.isValidName;
6869
import static jdk.internal.net.http.common.Utils.permissionForProxy;
6970
import static jdk.internal.net.http.common.Utils.stringOf;
@@ -373,7 +374,7 @@ private static Proxy proxyFor(Optional<ProxySelector> selector, URI uri) {
373374
if (proxy.type() != Proxy.Type.HTTP) {
374375
return null;
375376
}
376-
return proxy;
377+
return copyProxy(proxy);
377378
}
378379

379380
/**

0 commit comments

Comments
 (0)