mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-11 08:23:26 +00:00
8345625: Better HTTP connections
Reviewed-by: skoivu, rhalade, ahgross, dfuchs, jpai, aefimov
This commit is contained in:
parent
7aa3f31724
commit
d1ea951d39
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 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
|
||||
@ -24,8 +24,6 @@
|
||||
*/
|
||||
package sun.net.ftp.impl;
|
||||
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
@ -61,6 +59,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import sun.net.ftp.FtpDirEntry;
|
||||
import sun.net.ftp.FtpDirParser;
|
||||
import sun.net.ftp.FtpProtocolException;
|
||||
@ -68,6 +67,7 @@ import sun.net.ftp.FtpReplyCode;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import static sun.net.util.ProxyUtil.copyProxy;
|
||||
|
||||
public class FtpClient extends sun.net.ftp.FtpClient {
|
||||
|
||||
@ -954,7 +954,7 @@ public class FtpClient extends sun.net.ftp.FtpClient {
|
||||
}
|
||||
|
||||
public sun.net.ftp.FtpClient setProxy(Proxy p) {
|
||||
proxy = p;
|
||||
proxy = copyProxy(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
49
src/java.base/share/classes/sun/net/util/ProxyUtil.java
Normal file
49
src/java.base/share/classes/sun/net/util/ProxyUtil.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.net.util;
|
||||
|
||||
import sun.net.ApplicationProxy;
|
||||
|
||||
import java.net.Proxy;
|
||||
|
||||
public final class ProxyUtil {
|
||||
|
||||
private ProxyUtil() {}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Proxy} instance for the given proxy iff it is
|
||||
* neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, an
|
||||
* {@link ApplicationProxy} instance, nor already a {@code Proxy} instance.
|
||||
*/
|
||||
public static Proxy copyProxy(Proxy proxy) {
|
||||
return proxy == null
|
||||
|| proxy.getClass() == Proxy.class
|
||||
|| proxy instanceof ApplicationProxy
|
||||
? proxy
|
||||
: new Proxy(proxy.type(), proxy.address());
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 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
|
||||
@ -41,6 +41,8 @@ import sun.net.www.ParseUtil;
|
||||
import sun.net.www.protocol.http.AuthCacheImpl;
|
||||
import sun.net.www.protocol.http.HttpURLConnection;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import static sun.net.util.ProxyUtil.copyProxy;
|
||||
import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
|
||||
|
||||
/**
|
||||
@ -261,7 +263,7 @@ public class HttpClient extends NetworkClient {
|
||||
}
|
||||
|
||||
protected HttpClient(URL url, Proxy p, int to) throws IOException {
|
||||
proxy = (p == null) ? Proxy.NO_PROXY : p;
|
||||
proxy = p == null ? Proxy.NO_PROXY : copyProxy(p);
|
||||
this.host = url.getHost();
|
||||
this.url = url;
|
||||
port = url.getPort();
|
||||
@ -326,9 +328,7 @@ public class HttpClient extends NetworkClient {
|
||||
public static HttpClient New(URL url, Proxy p, int to, boolean useCache,
|
||||
HttpURLConnection httpuc) throws IOException
|
||||
{
|
||||
if (p == null) {
|
||||
p = Proxy.NO_PROXY;
|
||||
}
|
||||
p = p == null ? Proxy.NO_PROXY : copyProxy(p);
|
||||
HttpClient ret = null;
|
||||
/* see if one's already around */
|
||||
if (useCache) {
|
||||
|
||||
@ -43,6 +43,7 @@ import java.net.ProxySelector;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.security.Permission;
|
||||
|
||||
import sun.net.NetworkClient;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
import sun.net.www.MessageHeader;
|
||||
@ -53,6 +54,7 @@ import sun.net.ftp.FtpClient;
|
||||
import sun.net.ftp.FtpProtocolException;
|
||||
import sun.net.www.ParseUtil;
|
||||
|
||||
import static sun.net.util.ProxyUtil.copyProxy;
|
||||
|
||||
/**
|
||||
* This class Opens an FTP input (or output) stream given a URL.
|
||||
@ -234,7 +236,7 @@ public class FtpURLConnection extends URLConnection {
|
||||
throw new IOException("Failed to select a proxy", iae);
|
||||
}
|
||||
for (Proxy proxy : proxies) {
|
||||
p = proxy;
|
||||
p = copyProxy(proxy);
|
||||
if (p == null || p == Proxy.NO_PROXY ||
|
||||
p.type() == Proxy.Type.SOCKS) {
|
||||
break;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 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
|
||||
@ -33,11 +33,9 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.Proxy;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import sun.net.ftp.FtpClient;
|
||||
import sun.net.www.protocol.http.HttpURLConnection;
|
||||
|
||||
import static sun.net.util.ProxyUtil.copyProxy;
|
||||
|
||||
/** open an ftp connection given a URL */
|
||||
public class Handler extends java.net.URLStreamHandler {
|
||||
@ -57,11 +55,11 @@ public class Handler extends java.net.URLStreamHandler {
|
||||
return openConnection(u, null);
|
||||
}
|
||||
|
||||
protected java.net.URLConnection openConnection(URL u, Proxy p)
|
||||
protected java.net.URLConnection openConnection(URL u, Proxy proxy)
|
||||
throws IOException {
|
||||
FtpURLConnection connection = null;
|
||||
FtpURLConnection connection;
|
||||
try {
|
||||
connection = new FtpURLConnection(u, p);
|
||||
connection = new FtpURLConnection(u, copyProxy(proxy));
|
||||
} catch (IllegalArgumentException e) {
|
||||
var mfue = new MalformedURLException(e.getMessage());
|
||||
mfue.initCause(e);
|
||||
|
||||
@ -77,6 +77,7 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static sun.net.util.ProxyUtil.copyProxy;
|
||||
import static sun.net.www.protocol.http.AuthScheme.BASIC;
|
||||
import static sun.net.www.protocol.http.AuthScheme.DIGEST;
|
||||
import static sun.net.www.protocol.http.AuthScheme.NTLM;
|
||||
@ -854,7 +855,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
userHeaders = new MessageHeader();
|
||||
this.handler = handler;
|
||||
instProxy = p;
|
||||
instProxy = copyProxy(p);
|
||||
cookieHandler = CookieHandler.getDefault();
|
||||
cacheHandler = ResponseCache.getDefault();
|
||||
}
|
||||
@ -956,7 +957,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
final Iterator<Proxy> it = proxies.iterator();
|
||||
Proxy p;
|
||||
while (it.hasNext()) {
|
||||
p = it.next();
|
||||
p = copyProxy(it.next());
|
||||
try {
|
||||
if (!failedOnce) {
|
||||
http = getNewHttpClient(url, p, connectTimeout);
|
||||
|
||||
@ -1636,11 +1636,6 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
return Optional.ofNullable(userProxySelector);
|
||||
}
|
||||
|
||||
// Return the effective proxy that this client uses.
|
||||
ProxySelector proxySelector() {
|
||||
return proxySelector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocket.Builder newWebSocketBuilder() {
|
||||
// Make sure to pass the HttpClientFacade to the WebSocket builder.
|
||||
|
||||
@ -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
|
||||
@ -45,10 +45,10 @@ import jdk.internal.net.http.common.HttpHeadersBuilder;
|
||||
import jdk.internal.net.http.common.Utils;
|
||||
import jdk.internal.net.http.websocket.WebSocketRequest;
|
||||
|
||||
import static java.net.Authenticator.RequestorType.PROXY;
|
||||
import static java.net.Authenticator.RequestorType.SERVER;
|
||||
import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
|
||||
import static jdk.internal.net.http.common.Utils.ProxyHeaders;
|
||||
import static jdk.internal.net.http.common.Utils.copyProxy;
|
||||
|
||||
public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
|
||||
@ -127,15 +127,7 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
|
||||
}
|
||||
this.uri = requestURI;
|
||||
if (isWebSocket) {
|
||||
// WebSocket determines and sets the proxy itself
|
||||
this.proxy = ((HttpRequestImpl) request).proxy;
|
||||
} else {
|
||||
if (ps != null)
|
||||
this.proxy = retrieveProxy(ps, uri);
|
||||
else
|
||||
this.proxy = null;
|
||||
}
|
||||
this.proxy = retrieveProxy(request, ps, uri);
|
||||
this.expectContinue = request.expectContinue();
|
||||
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
|
||||
this.requestPublisher = request.bodyPublisher().orElse(null);
|
||||
@ -292,16 +284,27 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
@Override
|
||||
public boolean expectContinue() { return expectContinue; }
|
||||
|
||||
/** Retrieves the proxy, from the given ProxySelector, if there is one. */
|
||||
private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
|
||||
Proxy proxy = null;
|
||||
List<Proxy> pl = ps.select(uri);
|
||||
if (!pl.isEmpty()) {
|
||||
Proxy p = pl.get(0);
|
||||
if (p.type() == Proxy.Type.HTTP)
|
||||
proxy = p;
|
||||
/** Retrieves a copy of the proxy either from the given {@link HttpRequest} or {@link ProxySelector}, if there is one. */
|
||||
private static Proxy retrieveProxy(HttpRequest request, ProxySelector ps, URI uri) {
|
||||
|
||||
// WebSocket determines and sets the proxy itself
|
||||
if (request instanceof HttpRequestImpl requestImpl && requestImpl.isWebSocket) {
|
||||
return requestImpl.proxy;
|
||||
}
|
||||
return proxy;
|
||||
|
||||
// Try to find a matching one from the `ProxySelector`
|
||||
if (ps != null) {
|
||||
List<Proxy> pl = ps.select(uri);
|
||||
if (!pl.isEmpty()) {
|
||||
Proxy p = pl.getFirst();
|
||||
if (p.type() == Proxy.Type.HTTP) {
|
||||
return copyProxy(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
InetSocketAddress proxy() {
|
||||
@ -317,7 +320,7 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
@Override
|
||||
public void setProxy(Proxy proxy) {
|
||||
assert isWebSocket;
|
||||
this.proxy = proxy;
|
||||
this.proxy = copyProxy(proxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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
|
||||
@ -38,6 +38,7 @@ import java.io.UncheckedIOException;
|
||||
import java.lang.System.Logger.Level;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpTimeoutException;
|
||||
@ -78,7 +79,6 @@ import sun.net.www.HeaderParser;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static java.net.Authenticator.RequestorType.PROXY;
|
||||
import static java.net.Authenticator.RequestorType.SERVER;
|
||||
|
||||
@ -309,6 +309,17 @@ public final class Utils {
|
||||
: ! PROXY_AUTH_DISABLED_SCHEMES.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Proxy} instance for the given proxy iff it is
|
||||
* neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, nor already a
|
||||
* {@code Proxy} instance.
|
||||
*/
|
||||
public static Proxy copyProxy(Proxy proxy) {
|
||||
return proxy == null || proxy.getClass() == Proxy.class
|
||||
? proxy
|
||||
: new Proxy(proxy.type(), proxy.address());
|
||||
}
|
||||
|
||||
// WebSocket connection Upgrade headers
|
||||
private static final String HEADER_CONNECTION = "Connection";
|
||||
private static final String HEADER_UPGRADE = "Upgrade";
|
||||
|
||||
@ -59,6 +59,7 @@ import java.util.TreeSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static jdk.internal.net.http.common.Utils.copyProxy;
|
||||
import static jdk.internal.net.http.common.Utils.isValidName;
|
||||
import static jdk.internal.net.http.common.Utils.stringOf;
|
||||
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
|
||||
@ -369,7 +370,7 @@ public class OpeningHandshake {
|
||||
if (proxy.type() != Proxy.Type.HTTP) {
|
||||
return null;
|
||||
}
|
||||
return proxy;
|
||||
return copyProxy(proxy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user