Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ClientProperties.PROXY_URI & al in HttpUrlConnector #5091

Merged
merged 5 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -520,4 +520,19 @@ public static <T> T getValue(final Map<String, ?> properties, final String key,
public static <T> T getValue(final Map<String, ?> properties, final String key, final Class<T> type) {
return PropertiesHelper.getValue(properties, key, type, null);
}

/**
* Get the value of the specified property. If null, it will obtain it from System property.
* <p/>
* 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<String, ?> properties, String key, String systemKey) {
return PropertiesHelper.getValue(properties, key, System.getProperty(systemKey), String.class, null);
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -267,6 +268,23 @@ public interface ConnectionFactory {
* @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.
* <p>
* Implementation of the method MUST be thread-safe and MUST ensure that
* a dedicated {@link java.net.HttpURLConnection} instance is returned for concurrent
* requests.
* </p>
*
* @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.
*/
default HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException {
return (proxy == null) ? getConnection(url) : (HttpURLConnection) url.openConnection(proxy);
}
}

private static class DefaultConnectionFactory implements ConnectionFactory {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand All @@ -37,17 +42,19 @@
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;
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.ExternalProperties;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.ClientRequest;
import org.glassfish.jersey.client.ClientResponse;
Expand Down Expand Up @@ -314,10 +321,37 @@ protected void secureConnection(final JerseyClient client, final HttpURLConnecti
}
}

private static URI getProxyUriValue(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 ClientResponse _apply(final ClientRequest request) throws IOException {
final HttpURLConnection uc;

uc = this.connectionFactory.getConnection(request.getUri().toURL());
Proxy proxy = null;
Object proxyUri = request.getConfiguration().getProperties().get(ClientProperties.PROXY_URI);
jansupol marked this conversation as resolved.
Show resolved Hide resolved
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);
}
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);

final String httpMethod = request.getMethod();
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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.
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -72,6 +73,7 @@ public static List<Object[]> testData() {
{Apache5ConnectorProvider.class},
{JettyConnectorProvider.class},
{NettyConnectorProvider.class},
{HttpUrlConnectorProvider.class},
});
}

Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
senivam marked this conversation as resolved.
Show resolved Hide resolved
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand All @@ -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";
Expand All @@ -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);
Expand Down