From f850e5e1be272ca977561a25b4b75c8d1d496d84 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 22 Jun 2022 08:44:00 +0200 Subject: [PATCH 1/5] Support for proxy in HttpUrlConnector Signed-off-by: Jorge Bescos Gascon --- .../client/HttpUrlConnectorProvider.java | 8 ++- .../client/internal/HttpUrlConnector.java | 63 ++++++++++++++++--- .../client/internal/localization.properties | 3 +- .../jersey/client/HttpUrlConnectorTest.java | 18 +++--- .../connector/proxy/ProxySelectorTest.java | 46 ++++++++++++++ .../e2e/client/connector/proxy/ProxyTest.java | 5 +- .../ssl/SslHttpUrlConnectorTest.java | 16 ++--- 7 files changed, 130 insertions(+), 29 deletions(-) diff --git a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java index 7389781ece..0dab495299 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.net.HttpURLConnection; +import java.net.Proxy; import java.net.URL; import java.util.Map; import java.util.logging.Logger; @@ -263,17 +264,18 @@ public interface ConnectionFactory { *

* * @param url the endpoint URL. + * @param proxy the configured proxy or null. * @return the {@link java.net.HttpURLConnection}. * @throws java.io.IOException in case the connection cannot be provided. */ - public HttpURLConnection getConnection(URL url) throws IOException; + public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException; } private static class DefaultConnectionFactory implements ConnectionFactory { @Override - public HttpURLConnection getConnection(final URL url) throws IOException { - return (HttpURLConnection) url.openConnection(); + public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException { + return (HttpURLConnection) (proxy != null ? url.openConnection(proxy) : url.openConnection()); } } diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java index 443c8573ed..21d2cae3ba 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -21,13 +21,18 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.net.HttpURLConnection; +import java.net.InetSocketAddress; import java.net.ProtocolException; +import java.net.Proxy; +import java.net.Proxy.Type; import java.net.SocketTimeoutException; import java.net.URI; import java.net.URISyntaxException; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Arrays; +import java.util.Base64; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -39,15 +44,15 @@ import java.util.logging.Logger; import java.util.stream.Collectors; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; import javax.ws.rs.ProcessingException; import javax.ws.rs.client.Client; +import javax.ws.rs.core.Configuration; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; - import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; @@ -314,10 +319,54 @@ protected void secureConnection(final JerseyClient client, final HttpURLConnecti } } + private URI getProxyUri(Object proxy) { + if (proxy instanceof URI) { + return (URI) proxy; + } else if (proxy instanceof String) { + return URI.create((String) proxy); + } else { + throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); + } + } + + private String getFromConfigOrSystem(ClientRequest request, String clientProperty, String systemProperty) { + String result = request.resolveProperty(clientProperty, String.class); + if (result == null) { + result = System.getProperty(systemProperty); + } + return result; + } + + private URI getProxyUri(ClientRequest request) { + Configuration config = request.getConfiguration(); + Object proxyUri = config.getProperty(ClientProperties.PROXY_URI); + if (proxyUri == null) { + String proxyHost = System.getProperty("http.proxyHost"); + String proxyPort = System.getProperty("http.proxyPort"); + if (proxyHost != null && proxyPort != null) { + return URI.create(proxyHost + ":" + proxyPort); + } + } else { + return getProxyUri(proxyUri); + } + return null; + } + private ClientResponse _apply(final ClientRequest request) throws IOException { final HttpURLConnection uc; - - uc = this.connectionFactory.getConnection(request.getUri().toURL()); + Proxy proxy = null; + URI proxyUri = getProxyUri(request); + if (proxyUri != null) { + String username = getFromConfigOrSystem(request, ClientProperties.PROXY_USERNAME, "http.proxyUser"); + String password = getFromConfigOrSystem(request, ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); + if (username != null && password != null) { + StringBuilder auth = new StringBuilder().append(username).append(":").append(password); + String encoded = "Basic " + Base64.getEncoder().encodeToString(auth.toString().getBytes()); + request.getHeaders().put("Proxy-Authorization", Arrays.asList(encoded)); + } + proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())); + } + uc = this.connectionFactory.getConnection(request.getUri().toURL(), proxy); uc.setDoInput(true); final String httpMethod = request.getMethod(); diff --git a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties index 4bc0ae8e30..8e3823cde3 100644 --- a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties +++ b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0, which is available at @@ -84,3 +84,4 @@ error.request.cancelled=Request cancelled by the client call. error.listener.init=ClientLifecycleListener {0} failed to initialize properly. error.listener.close=ClientLifecycleListener {0} failed to close properly. error.shutdownhook.close=Client shutdown hook {0} failed. +wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI. diff --git a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java index 7cd91213bd..b7a7616b65 100644 --- a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java +++ b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java @@ -16,11 +16,14 @@ package org.glassfish.jersey.client; +import static org.junit.Assert.assertEquals; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.ProtocolException; +import java.net.Proxy; import java.net.SocketTimeoutException; import java.net.URI; import java.net.URL; @@ -30,6 +33,10 @@ import java.util.List; import java.util.Map; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSocketFactory; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; @@ -39,17 +46,10 @@ import javax.ws.rs.core.Link; import javax.ws.rs.core.Response; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSocketFactory; - import org.glassfish.jersey.client.internal.HttpUrlConnector; - import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.assertEquals; /** * Various tests for the default client connector. @@ -91,7 +91,7 @@ public void testConnectionTimeoutNoEntity() { public void testResolvedRequestUri() { HttpUrlConnectorProvider.ConnectionFactory factory = new HttpUrlConnectorProvider.ConnectionFactory() { @Override - public HttpURLConnection getConnection(URL endpointUrl) throws IOException { + public HttpURLConnection getConnection(URL endpointUrl, Proxy proxy) throws IOException { HttpURLConnection result = (HttpURLConnection) endpointUrl.openConnection(); return wrapRedirectedHttp(result); } @@ -435,7 +435,7 @@ public void testSSLConnection() { ClientRequest request = client.target("https://localhost:8080").request().buildGet().request(); HttpUrlConnectorProvider.ConnectionFactory factory = new HttpUrlConnectorProvider.ConnectionFactory() { @Override - public HttpURLConnection getConnection(URL endpointUrl) throws IOException { + public HttpURLConnection getConnection(URL endpointUrl, Proxy proxy) throws IOException { HttpURLConnection result = (HttpURLConnection) endpointUrl.openConnection(); return wrapNoContentHttps(result); } diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java index 4580facf24..facbcf5f58 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java @@ -24,6 +24,8 @@ import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider; import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.client.spi.ConnectorProvider; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; import org.glassfish.jersey.netty.connector.NettyConnectorProvider; @@ -44,6 +46,7 @@ import javax.ws.rs.core.Response; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; +import java.util.Base64; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -57,6 +60,8 @@ @RunWith(Parameterized.class) public class ProxySelectorTest { private static final String NO_PASS = "no-pass"; + private static final String PROXY_USERNAME = "proxy-user"; + private static final String PROXY_PASSWORD = "proxy-password"; @Parameterized.Parameters(name = "{index}: {0}") public static List testData() { @@ -65,6 +70,7 @@ public static List testData() { // {Apache5ConnectorProvider.class}, // {JettyConnectorProvider.class}, {NettyConnectorProvider.class}, + {HttpUrlConnectorProvider.class}, }); } @@ -95,6 +101,23 @@ public void testGet407() { } } + @Test + public void testGetSuccess() { + // Next applies for HttpUrlConnectorProvider. It seems Netty is not supporting user/pass in System properties + if (connectorProvider.getClass() == HttpUrlConnectorProvider.class) { + try { + System.setProperty("http.proxyUser", PROXY_USERNAME); + System.setProperty("http.proxyPassword", PROXY_PASSWORD); + Response response = target("proxyTest").request().get(); + response.bufferEntity(); + assertEquals(response.readEntity(String.class), 200, response.getStatus()); + } finally { + System.clearProperty("http.proxyUser"); + System.clearProperty("http.proxyPassword"); + } + } + } + private static Server server; @BeforeClass public static void startFakeProxy() { @@ -148,6 +171,29 @@ public void handle(String target, HttpServletResponse response) { if (request.getHeader(NO_PASS) != null) { response.setStatus(Integer.parseInt(request.getHeader(NO_PASS))); + } else if (request.getHeader("Proxy-Authorization") != null) { + String proxyAuthorization = request.getHeader("Proxy-Authorization"); + String decoded = new String(Base64.getDecoder().decode(proxyAuthorization.substring(6).getBytes())); + final String[] split = decoded.split(":"); + final String username = split[0]; + final String password = split[1]; + + if (!username.equals(PROXY_USERNAME)) { + response.setStatus(400); + System.out.println("Found unexpected username: " + username); + } + + if (!password.equals(PROXY_PASSWORD)) { + response.setStatus(400); + System.out.println("Found unexpected password: " + username); + } + + if (response.getStatus() != 400) { + response.setStatus(200); + if ("CONNECT".equalsIgnoreCase(baseRequest.getMethod())) { // NETTY way of doing proxy + httpConnect.add(baseRequest.getHttpChannel()); + } + } } else { response.setStatus(407); response.addHeader("Proxy-Authenticate", "Basic"); diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java index 93e69c2124..b30d39e29c 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java @@ -25,6 +25,7 @@ import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.client.spi.ConnectorProvider; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; import org.glassfish.jersey.netty.connector.NettyConnectorProvider; @@ -72,6 +73,7 @@ public static List testData() { {Apache5ConnectorProvider.class}, {JettyConnectorProvider.class}, {NettyConnectorProvider.class}, + {HttpUrlConnectorProvider.class}, }); } @@ -110,7 +112,8 @@ public void testGetSuccess() { client().property(ClientProperties.PROXY_USERNAME, ProxyTest.PROXY_USERNAME); client().property(ClientProperties.PROXY_PASSWORD, ProxyTest.PROXY_PASSWORD); Response response = target("proxyTest").request().get(); - assertEquals(200, response.getStatus()); + response.bufferEntity(); + assertEquals(response.readEntity(String.class), 200, response.getStatus()); } private static Server server; diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java index df3f1dcd4e..d81139588d 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java @@ -16,11 +16,15 @@ package org.glassfish.jersey.tests.e2e.client.connector.ssl; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.InetAddress; +import java.net.Proxy; import java.net.Socket; import java.net.URL; import java.util.List; @@ -30,13 +34,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.core.Response; - import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider; @@ -44,10 +47,7 @@ import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import org.glassfish.jersey.logging.LoggingFeature; - import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; /** * Test custom socket factory in HttpUrlConnection using SSL @@ -70,7 +70,7 @@ public void testSSLWithCustomSocketFactory() throws Exception { .connectorProvider(new HttpUrlConnectorProvider().connectionFactory( new HttpUrlConnectorProvider.ConnectionFactory() { @Override - public HttpURLConnection getConnection(final URL url) throws IOException { + public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException { HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory(socketFactory); return connection; From 9feb9f406640d97ff1e73414c6663aefcf581c02 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 22 Jun 2022 09:38:06 +0200 Subject: [PATCH 2/5] Support other connectors Signed-off-by: Jorge Bescos Gascon --- .../apache/connector/ApacheConnector.java | 18 +++--- .../apache5/connector/Apache5Connector.java | 17 +++-- .../jetty/connector/JettyConnector.java | 62 +++++++------------ .../jersey/client/ClientProperties.java | 21 ++++++- .../client/HttpUrlConnectorProvider.java | 2 +- .../client/internal/HttpUrlConnector.java | 31 +++++----- .../jersey/client/HttpUrlConnectorTest.java | 2 +- .../connector/proxy/ProxySelectorTest.java | 10 +-- .../jersey4003/LostResponseTest.java | 40 ++++++------ 9 files changed, 103 insertions(+), 100 deletions(-) diff --git a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java index 81e94b4b17..3820333642 100644 --- a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java +++ b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java @@ -51,6 +51,7 @@ import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.RequestEntityProcessing; +import org.glassfish.jersey.client.internal.HttpUrlConnector; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.PropertiesHelper; @@ -279,21 +280,18 @@ class ApacheConnector implements Connector { clientBuilder.setRetryHandler((HttpRequestRetryHandler) retryHandler); } - final Object proxyUri; - proxyUri = config.getProperty(ClientProperties.PROXY_URI); + URI proxyUri = HttpUrlConnector.getProxyUri(config); if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); - final HttpHost proxy = new HttpHost(u.getHost(), u.getPort(), u.getScheme()); - final String userName; - userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); + HttpHost proxy = new HttpHost(proxyUri.getHost(), proxyUri.getPort(), proxyUri.getScheme()); + String userName = ClientProperties.getValue(config.getProperties(), + ClientProperties.PROXY_USERNAME, "http.proxyUser"); if (userName != null) { - final String password; - password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); - + String password = ClientProperties.getValue(config.getProperties(), + ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); if (password != null) { final CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( - new AuthScope(u.getHost(), u.getPort()), + new AuthScope(proxyUri.getHost(), proxyUri.getPort()), new UsernamePasswordCredentials(userName, password) ); clientBuilder.setDefaultCredentialsProvider(credsProvider); diff --git a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java index 9d101055f2..c752210174 100644 --- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java +++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java @@ -93,6 +93,7 @@ import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.RequestEntityProcessing; +import org.glassfish.jersey.client.internal.HttpUrlConnector; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.PropertiesHelper; @@ -280,21 +281,19 @@ class Apache5Connector implements Connector { clientBuilder.setRetryStrategy((HttpRequestRetryStrategy) retryHandler); } - final Object proxyUri; - proxyUri = config.getProperty(ClientProperties.PROXY_URI); + URI proxyUri = HttpUrlConnector.getProxyUri(config); if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); - final HttpHost proxy = new HttpHost(u.getScheme(), u.getHost(), u.getPort()); - final String userName; - userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); + HttpHost proxy = new HttpHost(proxyUri.getScheme(), proxyUri.getHost(), proxyUri.getPort()); + String userName = ClientProperties.getValue(config.getProperties(), + ClientProperties.PROXY_USERNAME, "http.proxyUser"); if (userName != null) { - final String password; - password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); + String password = ClientProperties.getValue(config.getProperties(), + ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); if (password != null) { final CredentialsStore credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( - new AuthScope(u.getHost(), u.getPort()), + new AuthScope(proxyUri.getHost(), proxyUri.getPort()), new UsernamePasswordCredentials(userName, password.toCharArray()) ); clientBuilder.setDefaultCredentialsProvider(credsProvider); diff --git a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java index 780adc1e8a..26c962c3c4 100644 --- a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java +++ b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java @@ -31,37 +31,19 @@ import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; +import javax.net.ssl.SSLContext; import javax.ws.rs.ProcessingException; import javax.ws.rs.client.Client; import javax.ws.rs.core.Configuration; import javax.ws.rs.core.MultivaluedMap; -import javax.net.ssl.SSLContext; - -import org.eclipse.jetty.client.util.BasicAuthentication; -import org.eclipse.jetty.client.util.BytesContentProvider; -import org.eclipse.jetty.client.util.FutureResponseListener; -import org.eclipse.jetty.client.util.OutputStreamContentProvider; -import org.glassfish.jersey.client.ClientProperties; -import org.glassfish.jersey.client.ClientRequest; -import org.glassfish.jersey.client.ClientResponse; -import org.glassfish.jersey.client.spi.AsyncConnectorCallback; -import org.glassfish.jersey.client.spi.Connector; -import org.glassfish.jersey.internal.util.collection.ByteBufferInputStream; -import org.glassfish.jersey.internal.util.collection.NonBlockingInputStream; -import org.glassfish.jersey.message.internal.HeaderUtils; -import org.glassfish.jersey.message.internal.OutboundMessageContext; -import org.glassfish.jersey.message.internal.Statuses; - import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.ProxyConfiguration; @@ -71,6 +53,10 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.BasicAuthentication; +import org.eclipse.jetty.client.util.BytesContentProvider; +import org.eclipse.jetty.client.util.FutureResponseListener; +import org.eclipse.jetty.client.util.OutputStreamContentProvider; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; @@ -78,6 +64,17 @@ import org.eclipse.jetty.util.Jetty; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.ClientRequest; +import org.glassfish.jersey.client.ClientResponse; +import org.glassfish.jersey.client.internal.HttpUrlConnector; +import org.glassfish.jersey.client.spi.AsyncConnectorCallback; +import org.glassfish.jersey.client.spi.Connector; +import org.glassfish.jersey.internal.util.collection.ByteBufferInputStream; +import org.glassfish.jersey.internal.util.collection.NonBlockingInputStream; +import org.glassfish.jersey.message.internal.HeaderUtils; +import org.glassfish.jersey.message.internal.OutboundMessageContext; +import org.glassfish.jersey.message.internal.Statuses; /** * A {@link Connector} that utilizes the Jetty HTTP Client to send and receive @@ -187,17 +184,17 @@ class JettyConnector implements Connector { auth.addAuthentication((BasicAuthentication) basicAuthProvider); } - final Object proxyUri = config.getProperties().get(ClientProperties.PROXY_URI); + URI proxyUri = HttpUrlConnector.getProxyUri(config); if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); final ProxyConfiguration proxyConfig = client.getProxyConfiguration(); - proxyConfig.getProxies().add(new HttpProxy(u.getHost(), u.getPort())); - - final Object proxyUsername = config.getProperties().get(ClientProperties.PROXY_USERNAME); + proxyConfig.getProxies().add(new HttpProxy(proxyUri.getHost(), proxyUri.getPort())); + String proxyUsername = ClientProperties.getValue(config.getProperties(), + ClientProperties.PROXY_USERNAME, "http.proxyUser"); if (proxyUsername != null) { - final Object proxyPassword = config.getProperties().get(ClientProperties.PROXY_PASSWORD); - auth.addAuthentication(new BasicAuthentication(u, "<>", - String.valueOf(proxyUsername), String.valueOf(proxyPassword))); + String proxyPassword = ClientProperties.getValue(config.getProperties(), + ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); + auth.addAuthentication(new BasicAuthentication(proxyUri, "<>", + proxyUsername, proxyPassword)); } } @@ -223,17 +220,6 @@ class JettyConnector implements Connector { this.cookieStore = client.getCookieStore(); } - @SuppressWarnings("ChainOfInstanceofChecks") - private static URI getProxyUri(final Object proxy) { - if (proxy instanceof URI) { - return (URI) proxy; - } else if (proxy instanceof String) { - return URI.create((String) proxy); - } else { - throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); - } - } - /** * Get the {@link HttpClient}. * diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java index 7f1752ec71..9be3aa5596 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -520,4 +520,23 @@ public static T getValue(final Map properties, final String key, public static T getValue(final Map properties, final String key, final Class type) { return PropertiesHelper.getValue(properties, key, type, null); } + + /** + * Get the value of the specified property. If null, it will obtain it from System property. + *

+ * If the property is not set the method will return {@code null}. + * + * @param properties Map of properties to get the property value from. + * @param key Name of the property. + * @param systemKey Name of the System property. + * @return Value of the property or {@code null}. + * @since 2.37 + */ + public static String getValue(Map properties, String key, String systemKey) { + String value = PropertiesHelper.getValue(properties, key, String.class, null); + if (value == null) { + value = System.getProperty(systemKey); + } + return value; + } } diff --git a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java index 0dab495299..2fa7af2e4c 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java index 21d2cae3ba..5f6c425c35 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java @@ -319,7 +319,7 @@ protected void secureConnection(final JerseyClient client, final HttpURLConnecti } } - private URI getProxyUri(Object proxy) { + private static URI getProxyUriValue(Object proxy) { if (proxy instanceof URI) { return (URI) proxy; } else if (proxy instanceof String) { @@ -329,16 +329,15 @@ private URI getProxyUri(Object proxy) { } } - private String getFromConfigOrSystem(ClientRequest request, String clientProperty, String systemProperty) { - String result = request.resolveProperty(clientProperty, String.class); - if (result == null) { - result = System.getProperty(systemProperty); - } - return result; - } - - private URI getProxyUri(ClientRequest request) { - Configuration config = request.getConfiguration(); + /** + * Builds an URI from {@link ClientProperties#PROXY_URI}. + * In case it is not set, it will build it from System properties http.proxyHost and http.proxyPort. + * Otherwise returns null. + * + * @param config the configuration containing properties + * @return the URI or null + */ + public static URI getProxyUri(Configuration config) { Object proxyUri = config.getProperty(ClientProperties.PROXY_URI); if (proxyUri == null) { String proxyHost = System.getProperty("http.proxyHost"); @@ -347,7 +346,7 @@ private URI getProxyUri(ClientRequest request) { return URI.create(proxyHost + ":" + proxyPort); } } else { - return getProxyUri(proxyUri); + return getProxyUriValue(proxyUri); } return null; } @@ -355,10 +354,12 @@ private URI getProxyUri(ClientRequest request) { private ClientResponse _apply(final ClientRequest request) throws IOException { final HttpURLConnection uc; Proxy proxy = null; - URI proxyUri = getProxyUri(request); + URI proxyUri = getProxyUri(request.getConfiguration()); if (proxyUri != null) { - String username = getFromConfigOrSystem(request, ClientProperties.PROXY_USERNAME, "http.proxyUser"); - String password = getFromConfigOrSystem(request, ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); + String username = ClientProperties.getValue(request.getConfiguration().getProperties(), + ClientProperties.PROXY_USERNAME, "http.proxyUser"); + String password = ClientProperties.getValue(request.getConfiguration().getProperties(), + ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); if (username != null && password != null) { StringBuilder auth = new StringBuilder().append(username).append(":").append(password); String encoded = "Basic " + Base64.getEncoder().encodeToString(auth.toString().getBytes()); diff --git a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java index b7a7616b65..e45e038a10 100644 --- a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java +++ b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java index facbcf5f58..5ac8c7609d 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java @@ -66,9 +66,9 @@ public class ProxySelectorTest { @Parameterized.Parameters(name = "{index}: {0}") public static List testData() { return Arrays.asList(new Object[][]{ -// {ApacheConnectorProvider.class}, -// {Apache5ConnectorProvider.class}, -// {JettyConnectorProvider.class}, + {ApacheConnectorProvider.class}, + {Apache5ConnectorProvider.class}, + {JettyConnectorProvider.class}, {NettyConnectorProvider.class}, {HttpUrlConnectorProvider.class}, }); @@ -103,8 +103,8 @@ public void testGet407() { @Test public void testGetSuccess() { - // Next applies for HttpUrlConnectorProvider. It seems Netty is not supporting user/pass in System properties - if (connectorProvider.getClass() == HttpUrlConnectorProvider.class) { + // It seems Netty is not supporting user/pass in System properties + if (connectorProvider.getClass() != NettyConnectorProvider.class) { try { System.setProperty("http.proxyUser", PROXY_USERNAME); System.setProperty("http.proxyPassword", PROXY_PASSWORD); diff --git a/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java b/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java index 2ba8042961..1780d05a8d 100644 --- a/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java +++ b/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,28 +16,11 @@ package org.glassfish.jersey.tests.integration.jersey4003; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.HttpUrlConnectorProvider; -import org.glassfish.jersey.client.JerseyClientBuilder; -import org.glassfish.jersey.client.JerseyCompletionStageRxInvoker; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import org.mockito.Mockito; - -import javax.ws.rs.client.Client; -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.InvocationCallback; -import javax.ws.rs.client.ResponseProcessingException; -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; +import java.net.Proxy; import java.net.URL; import java.util.concurrent.CompletionStage; import java.util.concurrent.CountDownLatch; @@ -46,6 +29,23 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.InvocationCallback; +import javax.ws.rs.client.ResponseProcessingException; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.client.JerseyClientBuilder; +import org.glassfish.jersey.client.JerseyCompletionStageRxInvoker; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + public class LostResponseTest { private static final String DUMMY_URL = "http://foo"; @@ -59,7 +59,7 @@ public void setup() throws IOException { HttpUrlConnectorProvider.ConnectionFactory connectionFactory = Mockito.mock(HttpUrlConnectorProvider.ConnectionFactory.class); HttpURLConnection connection = Mockito.mock(HttpURLConnection.class); - Mockito.when(connectionFactory.getConnection(Mockito.any(URL.class))).thenReturn(connection); + Mockito.when(connectionFactory.getConnection(Mockito.any(URL.class), Mockito.any())).thenReturn(connection); OutputStream outputStream = Mockito.mock(OutputStream.class); Mockito.when(connection.getOutputStream()).thenReturn(outputStream); From ea85d100d7e53ff104cbeee1c0024cd0f6788b94 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 22 Jun 2022 12:15:25 +0200 Subject: [PATCH 3/5] Support nonProxyHosts Signed-off-by: Jorge Bescos Gascon --- .../apache/connector/ApacheConnector.java | 6 +- .../apache5/connector/Apache5Connector.java | 6 +- .../jetty/connector/JettyConnector.java | 6 +- .../client/internal/HttpUrlConnector.java | 55 +++++++++++++------ .../glassfish/jersey/ExternalProperties.java | 14 ++++- .../externalproperties/HttpProxyTest.java | 2 +- 6 files changed, 64 insertions(+), 25 deletions(-) diff --git a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java index 3820333642..d96290a6bb 100644 --- a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java +++ b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java @@ -47,6 +47,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; +import org.glassfish.jersey.ExternalProperties; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; @@ -282,12 +283,13 @@ class ApacheConnector implements Connector { URI proxyUri = HttpUrlConnector.getProxyUri(config); if (proxyUri != null) { + // TODO No proxy hosts? HttpHost proxy = new HttpHost(proxyUri.getHost(), proxyUri.getPort(), proxyUri.getScheme()); String userName = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_USERNAME, "http.proxyUser"); + ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); if (userName != null) { String password = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); + ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); if (password != null) { final CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( diff --git a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java index c752210174..87fba429cc 100644 --- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java +++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java @@ -89,6 +89,7 @@ import org.apache.hc.core5.util.TextUtils; import org.apache.hc.core5.util.Timeout; import org.apache.hc.core5.util.VersionInfo; +import org.glassfish.jersey.ExternalProperties; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; @@ -283,12 +284,13 @@ class Apache5Connector implements Connector { URI proxyUri = HttpUrlConnector.getProxyUri(config); if (proxyUri != null) { + // TODO No proxy hosts? HttpHost proxy = new HttpHost(proxyUri.getScheme(), proxyUri.getHost(), proxyUri.getPort()); String userName = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_USERNAME, "http.proxyUser"); + ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); if (userName != null) { String password = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); + ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); if (password != null) { final CredentialsStore credsProvider = new BasicCredentialsProvider(); diff --git a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java index 26c962c3c4..bb436d6917 100644 --- a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java +++ b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java @@ -64,6 +64,7 @@ import org.eclipse.jetty.util.Jetty; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.glassfish.jersey.ExternalProperties; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; @@ -186,13 +187,14 @@ class JettyConnector implements Connector { URI proxyUri = HttpUrlConnector.getProxyUri(config); if (proxyUri != null) { + // TODO No proxy hosts? final ProxyConfiguration proxyConfig = client.getProxyConfiguration(); proxyConfig.getProxies().add(new HttpProxy(proxyUri.getHost(), proxyUri.getPort())); String proxyUsername = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_USERNAME, "http.proxyUser"); + ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); if (proxyUsername != null) { String proxyPassword = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); + ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); auth.addAuthentication(new BasicAuthentication(proxyUri, "<>", proxyUsername, proxyPassword)); } diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java index 5f6c425c35..fbac32ae2b 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java @@ -42,6 +42,7 @@ import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.net.ssl.HostnameVerifier; @@ -53,6 +54,7 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; +import org.glassfish.jersey.ExternalProperties; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; @@ -338,34 +340,55 @@ private static URI getProxyUriValue(Object proxy) { * @return the URI or null */ public static URI getProxyUri(Configuration config) { + URI uri = null; Object proxyUri = config.getProperty(ClientProperties.PROXY_URI); if (proxyUri == null) { - String proxyHost = System.getProperty("http.proxyHost"); - String proxyPort = System.getProperty("http.proxyPort"); + String proxyHost = System.getProperty(ExternalProperties.HTTP_PROXY_HOST); + String proxyPort = System.getProperty(ExternalProperties.HTTP_PROXY_PORT); if (proxyHost != null && proxyPort != null) { - return URI.create(proxyHost + ":" + proxyPort); + if (proxyHost.startsWith("http://")) { + uri = URI.create(proxyHost + ":" + proxyPort); + } else { + uri = URI.create("http://" + proxyHost + ":" + proxyPort); + } } } else { - return getProxyUriValue(proxyUri); + uri = getProxyUriValue(proxyUri); } - return null; + return uri; } private ClientResponse _apply(final ClientRequest request) throws IOException { final HttpURLConnection uc; Proxy proxy = null; - URI proxyUri = getProxyUri(request.getConfiguration()); - if (proxyUri != null) { - String username = ClientProperties.getValue(request.getConfiguration().getProperties(), - ClientProperties.PROXY_USERNAME, "http.proxyUser"); - String password = ClientProperties.getValue(request.getConfiguration().getProperties(), - ClientProperties.PROXY_PASSWORD, "http.proxyPassword"); - if (username != null && password != null) { - StringBuilder auth = new StringBuilder().append(username).append(":").append(password); - String encoded = "Basic " + Base64.getEncoder().encodeToString(auth.toString().getBytes()); - request.getHeaders().put("Proxy-Authorization", Arrays.asList(encoded)); + boolean skipProxy = false; + // Evaluate HTTP_NON_PROXY_HOSTS if HTTP_PROXY_HOST is also set + if (System.getProperty(ExternalProperties.HTTP_PROXY_HOST) != null + && System.getProperty(ExternalProperties.HTTP_NON_PROXY_HOSTS) != null) { + String[] nonProxyHosts = System.getProperty(ExternalProperties.HTTP_NON_PROXY_HOSTS) + .trim().split("\\|"); + String currentHost = request.getUri().getHost(); + for (String nonProxyHost : nonProxyHosts) { + if (Pattern.matches(nonProxyHost, currentHost)) { + skipProxy = true; + break; + } + } + } + if (!skipProxy) { + URI proxyUri = getProxyUri(request.getConfiguration()); + if (proxyUri != null) { + String username = ClientProperties.getValue(request.getConfiguration().getProperties(), + ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); + String password = ClientProperties.getValue(request.getConfiguration().getProperties(), + ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); + if (username != null && password != null) { + StringBuilder auth = new StringBuilder().append(username).append(":").append(password); + String encoded = "Basic " + Base64.getEncoder().encodeToString(auth.toString().getBytes()); + request.getHeaders().put("Proxy-Authorization", Arrays.asList(encoded)); + } + proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())); } - proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())); } uc = this.connectionFactory.getConnection(request.getUri().toURL(), proxy); uc.setDoInput(true); diff --git a/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java b/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java index 04ef1bd323..a8f6ec6eee 100644 --- a/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java +++ b/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -32,11 +32,21 @@ public final class ExternalProperties { public static final String HTTP_PROXY_PORT = "http.proxyPort"; /** - * Property used to indicates the hosts that should be accessed + * Property used to indicate the hosts that should be accessed * without going through the proxy. */ public static final String HTTP_NON_PROXY_HOSTS = "http.nonProxyHosts"; + /** + * Property used to specify the user name to authenticate with the proxy. + */ + public static final String HTTP_PROXY_USER = "http.proxyUser"; + + /** + * Property used to specify the password to authenticate with the proxy. + */ + public static final String HTTP_PROXY_PASSWORD = "http.proxyPassword"; + /** * Prevent instantiation. */ diff --git a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java index 94100297f0..f74a55da14 100644 --- a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java +++ b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at From f738329040caadbd2100e3d779439f397bb7b355 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Thu, 23 Jun 2022 07:36:26 +0200 Subject: [PATCH 4/5] Revert proxy system properties from connectors Signed-off-by: Jorge Bescos Gascon --- .../apache/connector/ApacheConnector.java | 20 +++--- .../apache5/connector/Apache5Connector.java | 19 +++--- .../jetty/connector/JettyConnector.java | 64 +++++++++++------- .../jersey/client/ClientProperties.java | 6 +- .../client/internal/HttpUrlConnector.java | 67 ++++--------------- .../connector/proxy/ProxySelectorTest.java | 52 +------------- .../externalproperties/HttpProxyTest.java | 2 +- 7 files changed, 76 insertions(+), 154 deletions(-) diff --git a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java index d96290a6bb..81e94b4b17 100644 --- a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java +++ b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java @@ -47,12 +47,10 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; -import org.glassfish.jersey.ExternalProperties; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.RequestEntityProcessing; -import org.glassfish.jersey.client.internal.HttpUrlConnector; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.PropertiesHelper; @@ -281,19 +279,21 @@ class ApacheConnector implements Connector { clientBuilder.setRetryHandler((HttpRequestRetryHandler) retryHandler); } - URI proxyUri = HttpUrlConnector.getProxyUri(config); + final Object proxyUri; + proxyUri = config.getProperty(ClientProperties.PROXY_URI); if (proxyUri != null) { - // TODO No proxy hosts? - HttpHost proxy = new HttpHost(proxyUri.getHost(), proxyUri.getPort(), proxyUri.getScheme()); - String userName = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); + final URI u = getProxyUri(proxyUri); + final HttpHost proxy = new HttpHost(u.getHost(), u.getPort(), u.getScheme()); + final String userName; + userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); if (userName != null) { - String password = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); + final String password; + password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); + if (password != null) { final CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( - new AuthScope(proxyUri.getHost(), proxyUri.getPort()), + new AuthScope(u.getHost(), u.getPort()), new UsernamePasswordCredentials(userName, password) ); clientBuilder.setDefaultCredentialsProvider(credsProvider); diff --git a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java index 87fba429cc..9d101055f2 100644 --- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java +++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java @@ -89,12 +89,10 @@ import org.apache.hc.core5.util.TextUtils; import org.apache.hc.core5.util.Timeout; import org.apache.hc.core5.util.VersionInfo; -import org.glassfish.jersey.ExternalProperties; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.RequestEntityProcessing; -import org.glassfish.jersey.client.internal.HttpUrlConnector; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.PropertiesHelper; @@ -282,20 +280,21 @@ class Apache5Connector implements Connector { clientBuilder.setRetryStrategy((HttpRequestRetryStrategy) retryHandler); } - URI proxyUri = HttpUrlConnector.getProxyUri(config); + final Object proxyUri; + proxyUri = config.getProperty(ClientProperties.PROXY_URI); if (proxyUri != null) { - // TODO No proxy hosts? - HttpHost proxy = new HttpHost(proxyUri.getScheme(), proxyUri.getHost(), proxyUri.getPort()); - String userName = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); + final URI u = getProxyUri(proxyUri); + final HttpHost proxy = new HttpHost(u.getScheme(), u.getHost(), u.getPort()); + final String userName; + userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); if (userName != null) { - String password = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); + final String password; + password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); if (password != null) { final CredentialsStore credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( - new AuthScope(proxyUri.getHost(), proxyUri.getPort()), + new AuthScope(u.getHost(), u.getPort()), new UsernamePasswordCredentials(userName, password.toCharArray()) ); clientBuilder.setDefaultCredentialsProvider(credsProvider); diff --git a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java index bb436d6917..780adc1e8a 100644 --- a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java +++ b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java @@ -31,19 +31,37 @@ import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; -import javax.net.ssl.SSLContext; import javax.ws.rs.ProcessingException; import javax.ws.rs.client.Client; import javax.ws.rs.core.Configuration; import javax.ws.rs.core.MultivaluedMap; +import javax.net.ssl.SSLContext; + +import org.eclipse.jetty.client.util.BasicAuthentication; +import org.eclipse.jetty.client.util.BytesContentProvider; +import org.eclipse.jetty.client.util.FutureResponseListener; +import org.eclipse.jetty.client.util.OutputStreamContentProvider; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.ClientRequest; +import org.glassfish.jersey.client.ClientResponse; +import org.glassfish.jersey.client.spi.AsyncConnectorCallback; +import org.glassfish.jersey.client.spi.Connector; +import org.glassfish.jersey.internal.util.collection.ByteBufferInputStream; +import org.glassfish.jersey.internal.util.collection.NonBlockingInputStream; +import org.glassfish.jersey.message.internal.HeaderUtils; +import org.glassfish.jersey.message.internal.OutboundMessageContext; +import org.glassfish.jersey.message.internal.Statuses; + import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.ProxyConfiguration; @@ -53,10 +71,6 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.client.util.BasicAuthentication; -import org.eclipse.jetty.client.util.BytesContentProvider; -import org.eclipse.jetty.client.util.FutureResponseListener; -import org.eclipse.jetty.client.util.OutputStreamContentProvider; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; @@ -64,18 +78,6 @@ import org.eclipse.jetty.util.Jetty; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.glassfish.jersey.ExternalProperties; -import org.glassfish.jersey.client.ClientProperties; -import org.glassfish.jersey.client.ClientRequest; -import org.glassfish.jersey.client.ClientResponse; -import org.glassfish.jersey.client.internal.HttpUrlConnector; -import org.glassfish.jersey.client.spi.AsyncConnectorCallback; -import org.glassfish.jersey.client.spi.Connector; -import org.glassfish.jersey.internal.util.collection.ByteBufferInputStream; -import org.glassfish.jersey.internal.util.collection.NonBlockingInputStream; -import org.glassfish.jersey.message.internal.HeaderUtils; -import org.glassfish.jersey.message.internal.OutboundMessageContext; -import org.glassfish.jersey.message.internal.Statuses; /** * A {@link Connector} that utilizes the Jetty HTTP Client to send and receive @@ -185,18 +187,17 @@ class JettyConnector implements Connector { auth.addAuthentication((BasicAuthentication) basicAuthProvider); } - URI proxyUri = HttpUrlConnector.getProxyUri(config); + final Object proxyUri = config.getProperties().get(ClientProperties.PROXY_URI); if (proxyUri != null) { - // TODO No proxy hosts? + final URI u = getProxyUri(proxyUri); final ProxyConfiguration proxyConfig = client.getProxyConfiguration(); - proxyConfig.getProxies().add(new HttpProxy(proxyUri.getHost(), proxyUri.getPort())); - String proxyUsername = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); + proxyConfig.getProxies().add(new HttpProxy(u.getHost(), u.getPort())); + + final Object proxyUsername = config.getProperties().get(ClientProperties.PROXY_USERNAME); if (proxyUsername != null) { - String proxyPassword = ClientProperties.getValue(config.getProperties(), - ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); - auth.addAuthentication(new BasicAuthentication(proxyUri, "<>", - proxyUsername, proxyPassword)); + final Object proxyPassword = config.getProperties().get(ClientProperties.PROXY_PASSWORD); + auth.addAuthentication(new BasicAuthentication(u, "<>", + String.valueOf(proxyUsername), String.valueOf(proxyPassword))); } } @@ -222,6 +223,17 @@ class JettyConnector implements Connector { this.cookieStore = client.getCookieStore(); } + @SuppressWarnings("ChainOfInstanceofChecks") + private static URI getProxyUri(final Object proxy) { + if (proxy instanceof URI) { + return (URI) proxy; + } else if (proxy instanceof String) { + return URI.create((String) proxy); + } else { + throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); + } + } + /** * Get the {@link HttpClient}. * diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java index 9be3aa5596..4b42f10297 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java @@ -533,10 +533,6 @@ public static T getValue(final Map properties, final String key, * @since 2.37 */ public static String getValue(Map properties, String key, String systemKey) { - String value = PropertiesHelper.getValue(properties, key, String.class, null); - if (value == null) { - value = System.getProperty(systemKey); - } - return value; + return PropertiesHelper.getValue(properties, key, System.getProperty(systemKey), String.class, null); } } diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java index fbac32ae2b..ef85fa8eaf 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java @@ -331,64 +331,25 @@ private static URI getProxyUriValue(Object proxy) { } } - /** - * Builds an URI from {@link ClientProperties#PROXY_URI}. - * In case it is not set, it will build it from System properties http.proxyHost and http.proxyPort. - * Otherwise returns null. - * - * @param config the configuration containing properties - * @return the URI or null - */ - public static URI getProxyUri(Configuration config) { - URI uri = null; - Object proxyUri = config.getProperty(ClientProperties.PROXY_URI); - if (proxyUri == null) { - String proxyHost = System.getProperty(ExternalProperties.HTTP_PROXY_HOST); - String proxyPort = System.getProperty(ExternalProperties.HTTP_PROXY_PORT); - if (proxyHost != null && proxyPort != null) { - if (proxyHost.startsWith("http://")) { - uri = URI.create(proxyHost + ":" + proxyPort); - } else { - uri = URI.create("http://" + proxyHost + ":" + proxyPort); - } - } - } else { - uri = getProxyUriValue(proxyUri); - } - return uri; - } - private ClientResponse _apply(final ClientRequest request) throws IOException { final HttpURLConnection uc; Proxy proxy = null; - boolean skipProxy = false; - // Evaluate HTTP_NON_PROXY_HOSTS if HTTP_PROXY_HOST is also set - if (System.getProperty(ExternalProperties.HTTP_PROXY_HOST) != null - && System.getProperty(ExternalProperties.HTTP_NON_PROXY_HOSTS) != null) { - String[] nonProxyHosts = System.getProperty(ExternalProperties.HTTP_NON_PROXY_HOSTS) - .trim().split("\\|"); - String currentHost = request.getUri().getHost(); - for (String nonProxyHost : nonProxyHosts) { - if (Pattern.matches(nonProxyHost, currentHost)) { - skipProxy = true; - break; - } - } - } - if (!skipProxy) { - URI proxyUri = getProxyUri(request.getConfiguration()); - if (proxyUri != null) { - String username = ClientProperties.getValue(request.getConfiguration().getProperties(), - ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); - String password = ClientProperties.getValue(request.getConfiguration().getProperties(), - ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); - if (username != null && password != null) { - StringBuilder auth = new StringBuilder().append(username).append(":").append(password); - String encoded = "Basic " + Base64.getEncoder().encodeToString(auth.toString().getBytes()); - request.getHeaders().put("Proxy-Authorization", Arrays.asList(encoded)); + Object proxyUri = request.getConfiguration().getProperties().get(ClientProperties.PROXY_URI); + if (proxyUri != null) { + URI uri = getProxyUriValue(proxyUri); + String username = ClientProperties.getValue(request.getConfiguration().getProperties(), + ClientProperties.PROXY_USERNAME, ExternalProperties.HTTP_PROXY_USER); + String password = ClientProperties.getValue(request.getConfiguration().getProperties(), + ClientProperties.PROXY_PASSWORD, ExternalProperties.HTTP_PROXY_PASSWORD); + if (username != null) { + StringBuilder auth = new StringBuilder().append(username).append(":"); + if (password != null) { + auth.append(password); } - proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())); + String encoded = "Basic " + Base64.getEncoder().encodeToString(auth.toString().getBytes()); + request.getHeaders().put("Proxy-Authorization", Arrays.asList(encoded)); } + proxy = new Proxy(Type.HTTP, new InetSocketAddress(uri.getHost(), uri.getPort())); } uc = this.connectionFactory.getConnection(request.getUri().toURL(), proxy); uc.setDoInput(true); diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java index 5ac8c7609d..4580facf24 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java @@ -24,8 +24,6 @@ import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider; import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.ClientProperties; -import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.client.spi.ConnectorProvider; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; import org.glassfish.jersey.netty.connector.NettyConnectorProvider; @@ -46,7 +44,6 @@ import javax.ws.rs.core.Response; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; -import java.util.Base64; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -60,17 +57,14 @@ @RunWith(Parameterized.class) public class ProxySelectorTest { private static final String NO_PASS = "no-pass"; - private static final String PROXY_USERNAME = "proxy-user"; - private static final String PROXY_PASSWORD = "proxy-password"; @Parameterized.Parameters(name = "{index}: {0}") public static List testData() { return Arrays.asList(new Object[][]{ - {ApacheConnectorProvider.class}, - {Apache5ConnectorProvider.class}, - {JettyConnectorProvider.class}, +// {ApacheConnectorProvider.class}, +// {Apache5ConnectorProvider.class}, +// {JettyConnectorProvider.class}, {NettyConnectorProvider.class}, - {HttpUrlConnectorProvider.class}, }); } @@ -101,23 +95,6 @@ public void testGet407() { } } - @Test - public void testGetSuccess() { - // It seems Netty is not supporting user/pass in System properties - if (connectorProvider.getClass() != NettyConnectorProvider.class) { - try { - System.setProperty("http.proxyUser", PROXY_USERNAME); - System.setProperty("http.proxyPassword", PROXY_PASSWORD); - Response response = target("proxyTest").request().get(); - response.bufferEntity(); - assertEquals(response.readEntity(String.class), 200, response.getStatus()); - } finally { - System.clearProperty("http.proxyUser"); - System.clearProperty("http.proxyPassword"); - } - } - } - private static Server server; @BeforeClass public static void startFakeProxy() { @@ -171,29 +148,6 @@ public void handle(String target, HttpServletResponse response) { if (request.getHeader(NO_PASS) != null) { response.setStatus(Integer.parseInt(request.getHeader(NO_PASS))); - } else if (request.getHeader("Proxy-Authorization") != null) { - String proxyAuthorization = request.getHeader("Proxy-Authorization"); - String decoded = new String(Base64.getDecoder().decode(proxyAuthorization.substring(6).getBytes())); - final String[] split = decoded.split(":"); - final String username = split[0]; - final String password = split[1]; - - if (!username.equals(PROXY_USERNAME)) { - response.setStatus(400); - System.out.println("Found unexpected username: " + username); - } - - if (!password.equals(PROXY_PASSWORD)) { - response.setStatus(400); - System.out.println("Found unexpected password: " + username); - } - - if (response.getStatus() != 400) { - response.setStatus(200); - if ("CONNECT".equalsIgnoreCase(baseRequest.getMethod())) { // NETTY way of doing proxy - httpConnect.add(baseRequest.getHttpChannel()); - } - } } else { response.setStatus(407); response.addHeader("Proxy-Authenticate", "Basic"); diff --git a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java index f74a55da14..94100297f0 100644 --- a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java +++ b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at From 7fe4ad39c0e86ec2f93a57fac33d19ecc0c48de2 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Fri, 24 Jun 2022 13:39:08 +0200 Subject: [PATCH 5/5] Review comments Signed-off-by: Jorge Bescos Gascon --- .../client/HttpUrlConnectorProvider.java | 22 ++++++++++++++++--- .../jersey/client/HttpUrlConnectorTest.java | 18 +++++++-------- .../ssl/SslHttpUrlConnectorTest.java | 16 +++++++------- .../externalproperties/HttpProxyTest.java | 2 +- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java index 2fa7af2e4c..25a6d78cf5 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java @@ -255,6 +255,20 @@ protected Connector createHttpUrlConnector(Client client, ConnectionFactory conn */ public interface ConnectionFactory { + /** + * Get a {@link java.net.HttpURLConnection} for a given URL. + *

+ * Implementation of the method MUST be thread-safe and MUST ensure that + * a dedicated {@link java.net.HttpURLConnection} instance is returned for concurrent + * requests. + *

+ * + * @param url the endpoint URL. + * @return the {@link java.net.HttpURLConnection}. + * @throws java.io.IOException in case the connection cannot be provided. + */ + public HttpURLConnection getConnection(URL url) throws IOException; + /** * Get a {@link java.net.HttpURLConnection} for a given URL. *

@@ -268,14 +282,16 @@ public interface ConnectionFactory { * @return the {@link java.net.HttpURLConnection}. * @throws java.io.IOException in case the connection cannot be provided. */ - public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException; + default HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException { + return (proxy == null) ? getConnection(url) : (HttpURLConnection) url.openConnection(proxy); + } } private static class DefaultConnectionFactory implements ConnectionFactory { @Override - public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException { - return (HttpURLConnection) (proxy != null ? url.openConnection(proxy) : url.openConnection()); + public HttpURLConnection getConnection(final URL url) throws IOException { + return (HttpURLConnection) url.openConnection(); } } diff --git a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java index e45e038a10..5bb7a78780 100644 --- a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java +++ b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java @@ -16,14 +16,11 @@ package org.glassfish.jersey.client; -import static org.junit.Assert.assertEquals; - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.ProtocolException; -import java.net.Proxy; import java.net.SocketTimeoutException; import java.net.URI; import java.net.URL; @@ -33,10 +30,6 @@ import java.util.List; import java.util.Map; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSocketFactory; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; @@ -46,10 +39,17 @@ import javax.ws.rs.core.Link; import javax.ws.rs.core.Response; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSocketFactory; + import org.glassfish.jersey.client.internal.HttpUrlConnector; + import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; +import static org.junit.Assert.assertEquals; /** * Various tests for the default client connector. @@ -91,7 +91,7 @@ public void testConnectionTimeoutNoEntity() { public void testResolvedRequestUri() { HttpUrlConnectorProvider.ConnectionFactory factory = new HttpUrlConnectorProvider.ConnectionFactory() { @Override - public HttpURLConnection getConnection(URL endpointUrl, Proxy proxy) throws IOException { + public HttpURLConnection getConnection(URL endpointUrl) throws IOException { HttpURLConnection result = (HttpURLConnection) endpointUrl.openConnection(); return wrapRedirectedHttp(result); } @@ -435,7 +435,7 @@ public void testSSLConnection() { ClientRequest request = client.target("https://localhost:8080").request().buildGet().request(); HttpUrlConnectorProvider.ConnectionFactory factory = new HttpUrlConnectorProvider.ConnectionFactory() { @Override - public HttpURLConnection getConnection(URL endpointUrl, Proxy proxy) throws IOException { + public HttpURLConnection getConnection(URL endpointUrl) throws IOException { HttpURLConnection result = (HttpURLConnection) endpointUrl.openConnection(); return wrapNoContentHttps(result); } diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java index d81139588d..df3f1dcd4e 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslHttpUrlConnectorTest.java @@ -16,15 +16,11 @@ package org.glassfish.jersey.tests.e2e.client.connector.ssl; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.InetAddress; -import java.net.Proxy; import java.net.Socket; import java.net.URL; import java.util.List; @@ -34,20 +30,24 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.core.Response; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; + import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import org.glassfish.jersey.logging.LoggingFeature; + import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * Test custom socket factory in HttpUrlConnection using SSL @@ -70,7 +70,7 @@ public void testSSLWithCustomSocketFactory() throws Exception { .connectorProvider(new HttpUrlConnectorProvider().connectionFactory( new HttpUrlConnectorProvider.ConnectionFactory() { @Override - public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException { + public HttpURLConnection getConnection(final URL url) throws IOException { HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory(socketFactory); return connection; diff --git a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java index 94100297f0..f74a55da14 100644 --- a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java +++ b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at