diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java index c2841c9748b0..96a43f9b0711 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java @@ -147,7 +147,7 @@ public void successfulResponse_SlowResponseHandler_ThrowsApiCallTimeoutException } @Test - public void slowApiAttempt_ThrowsApiCallAttemptTimeoutException() { + public void slowApiAttempt_ThrowsApiCallAttemptTimeoutException() { httpClient = testAsyncClientBuilder() .apiCallTimeout(API_CALL_TIMEOUT) .apiCallAttemptTimeout(Duration.ofMillis(100)) diff --git a/http-clients/apache-client/pom.xml b/http-clients/apache-client/pom.xml index 8e8b725b9c0b..bf8f603c2f2f 100644 --- a/http-clients/apache-client/pom.xml +++ b/http-clients/apache-client/pom.xml @@ -67,6 +67,11 @@ junit test + + org.assertj + assertj-core + test + org.hamcrest hamcrest-all diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java index 4dc780ad110c..55f344807453 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java @@ -18,6 +18,7 @@ import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; +import static software.amazon.awssdk.http.SdkHttpConfigurationOption.CONNECTION_ACQUIRE_TIMEOUT; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.CONNECTION_TIMEOUT; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.MAX_CONNECTIONS; @@ -78,6 +79,7 @@ import software.amazon.awssdk.http.apache.internal.utils.ApacheUtils; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.Validate; /** * An implementation of {@link SdkHttpClient} that uses Apache HTTP client to communicate with the service. This is the most @@ -140,10 +142,11 @@ private void addProxyConfig(HttpClientBuilder builder, ProxyConfiguration proxyConfiguration) { if (isProxyEnabled(proxyConfiguration)) { - log.debug(() -> "Configuring Proxy. Proxy Host: " + proxyConfiguration.endpoint()); + log.debug(() -> "Configuring Proxy. Proxy Host: " + proxyConfiguration.host()); - builder.setRoutePlanner(new SdkProxyRoutePlanner(proxyConfiguration.endpoint().getHost(), - proxyConfiguration.endpoint().getPort(), + builder.setRoutePlanner(new SdkProxyRoutePlanner(proxyConfiguration.host(), + proxyConfiguration.port(), + proxyConfiguration.scheme(), proxyConfiguration.nonProxyHosts())); if (isAuthenticatedProxy(proxyConfiguration)) { @@ -164,9 +167,8 @@ private boolean isAuthenticatedProxy(ProxyConfiguration proxyConfiguration) { } private boolean isProxyEnabled(ProxyConfiguration proxyConfiguration) { - return proxyConfiguration.endpoint() != null - && proxyConfiguration.endpoint().getHost() != null - && proxyConfiguration.endpoint().getPort() > 0; + return proxyConfiguration.host() != null + && proxyConfiguration.port() > 0; } @Override @@ -240,6 +242,7 @@ private ApacheHttpRequestConfig createRequestConfig(DefaultBuilder builder, return ApacheHttpRequestConfig.builder() .socketTimeout(resolvedOptions.get(READ_TIMEOUT)) .connectionTimeout(resolvedOptions.get(CONNECTION_TIMEOUT)) + .connectionAcquireTimeout(resolvedOptions.get(CONNECTION_ACQUIRE_TIMEOUT)) .proxyConfiguration(builder.proxyConfiguration) .localAddress(Optional.ofNullable(builder.localAddress).orElse(null)) .expectContinueEnabled(Optional.ofNullable(builder.expectContinueEnabled) @@ -273,6 +276,13 @@ public interface Builder extends SdkHttpClient.Builder */ Builder connectionTimeout(Duration connectionTimeout); + /** + * The amount of time to wait when acquiring a connection from the pool before giving up and timing out. + * @param connectionAcquisitionTimeout the timeout duration + * @return this builder for method chaining. + */ + Builder connectionAcquisitionTimeout(Duration connectionAcquisitionTimeout); + /** * The maximum number of connections allowed in the connection pool. Each built HTTP client has it's own private * connection pool. @@ -336,6 +346,22 @@ public void setConnectionTimeout(Duration connectionTimeout) { connectionTimeout(connectionTimeout); } + /** + * The amount of time to wait when acquiring a connection from the pool before giving up and timing out. + * @param connectionAcquisitionTimeout the timeout duration + * @return this builder for method chaining. + */ + @Override + public Builder connectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) { + Validate.isPositive(connectionAcquisitionTimeout, "connectionAcquisitionTimeout"); + standardOptions.put(CONNECTION_ACQUIRE_TIMEOUT, connectionAcquisitionTimeout); + return this; + } + + public void setConnectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) { + connectionAcquisitionTimeout(connectionAcquisitionTimeout); + } + @Override public Builder maxConnections(Integer maxConnections) { standardOptions.put(MAX_CONNECTIONS, maxConnections); diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java index fc7137ca8807..aa2c77ae88b1 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java @@ -18,11 +18,14 @@ import static software.amazon.awssdk.utils.StringUtils.isEmpty; import java.net.URI; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import software.amazon.awssdk.annotations.ReviewBeforeRelease; +import java.util.stream.Collectors; import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.utils.ProxySystemSetting; +import software.amazon.awssdk.utils.StringUtils; import software.amazon.awssdk.utils.ToString; import software.amazon.awssdk.utils.Validate; import software.amazon.awssdk.utils.builder.CopyableBuilder; @@ -31,7 +34,6 @@ /** * Configuration that defines how to communicate via an HTTP proxy. */ -@ReviewBeforeRelease("Review which options are required and which are optional.") @SdkPublicApi public final class ProxyConfiguration implements ToCopyableBuilder { @@ -42,6 +44,10 @@ public final class ProxyConfiguration implements ToCopyableBuilder nonProxyHosts; private final Boolean preemptiveBasicAuthenticationEnabled; + private final Boolean useSystemPropertyValues; + private final String host; + private final int port; + private final String scheme; /** * Initialize this configuration. Private to require use of {@link #builder()}. @@ -52,18 +58,38 @@ private ProxyConfiguration(DefaultClientProxyConfigurationBuilder builder) { this.password = builder.password; this.ntlmDomain = builder.ntlmDomain; this.ntlmWorkstation = builder.ntlmWorkstation; - this.nonProxyHosts = Collections.unmodifiableSet(new HashSet<>(builder.nonProxyHosts)); + this.nonProxyHosts = builder.nonProxyHosts; this.preemptiveBasicAuthenticationEnabled = builder.preemptiveBasicAuthenticationEnabled == null ? Boolean.FALSE : builder.preemptiveBasicAuthenticationEnabled; + this.useSystemPropertyValues = builder.useSystemPropertyValues; + this.host = resolveHost(); + this.port = resolvePort(); + this.scheme = resolveScheme(); } /** - * The endpoint of the proxy server that the SDK should connect through. + * Returns the proxy host name either from the configured endpoint or + * from the "http.proxyHost" system property if {@link Builder#useSystemPropertyValues(Boolean)} is set to true. + */ + public String host() { + return host; + } + + /** + * Returns the proxy port either from the configured endpoint or + * from the "http.proxyPort" system property if {@link Builder#useSystemPropertyValues(Boolean)} is set to true. * - * @see Builder#endpoint(URI) + * If no value is found in neither of the above options, the default value of 0 is returned. + */ + public int port() { + return port; + } + + /** + * Returns the {@link URI#scheme} from the configured endpoint. Otherwise return null. */ - public URI endpoint() { - return endpoint; + public String scheme() { + return scheme; } /** @@ -72,7 +98,7 @@ public URI endpoint() { * @see Builder#password(String) */ public String username() { - return username; + return resolveValue(username, ProxySystemSetting.PROXY_USERNAME); } /** @@ -81,7 +107,7 @@ public String username() { * @see Builder#password(String) */ public String password() { - return password; + return resolveValue(password, ProxySystemSetting.PROXY_PASSWORD); } /** @@ -105,11 +131,16 @@ public String ntlmWorkstation() { /** * The hosts that the client is allowed to access without going through the proxy. * + * If the value is not set on the object, the value represent by "http.nonProxyHosts" system property is returned. + * If system property is also not set, an unmodifiable empty set is returned. + * * @see Builder#nonProxyHosts(Set) */ - @ReviewBeforeRelease("Revisit the presentation of this option and support http.nonProxyHosts property") public Set nonProxyHosts() { - return nonProxyHosts; + Set hosts = nonProxyHosts == null && useSystemPropertyValues ? parseNonProxyHostsProperty() + : nonProxyHosts; + + return Collections.unmodifiableSet(hosts != null ? hosts : Collections.emptySet()); } /** @@ -152,6 +183,54 @@ public String toString() { .build(); } + + private String resolveHost() { + return endpoint != null ? endpoint.getHost() + : resolveValue(null, ProxySystemSetting.PROXY_HOST); + } + + private int resolvePort() { + int port = 0; + + if (endpoint != null) { + port = endpoint.getPort(); + } else if (useSystemPropertyValues) { + port = ProxySystemSetting.PROXY_PORT.getStringValue() + .map(Integer::parseInt) + .orElse(0); + } + + return port; + } + + public String resolveScheme() { + return endpoint != null ? endpoint.getScheme() : null; + } + + /** + * Uses the configuration options, system setting property and returns the final value of the given member. + */ + private String resolveValue(String value, ProxySystemSetting systemSetting) { + return value == null && useSystemPropertyValues ? systemSetting.getStringValue().orElse(null) + : value; + } + + /** + * Returns the Java system property for nonProxyHosts as set of Strings. + * See http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html. + */ + private Set parseNonProxyHostsProperty() { + String nonProxyHosts = ProxySystemSetting.NON_PROXY_HOSTS.getStringValue().orElse(null); + + if (!StringUtils.isEmpty(nonProxyHosts)) { + return Arrays.stream(nonProxyHosts.split("\\|")) + .map(String::toLowerCase) + .map(s -> s.replace("*", ".*?")) + .collect(Collectors.toSet()); + } + return Collections.emptySet(); + } + /** * A builder for {@link ProxyConfiguration}. * @@ -202,6 +281,15 @@ public interface Builder extends CopyableBuilder { */ Builder preemptiveBasicAuthenticationEnabled(Boolean preemptiveBasicAuthenticationEnabled); + /** + * Option whether to use system property values from {@link ProxySystemSetting} if any of the config options are missing. + * + * This value is set to "true" by default which means SDK will automatically use system property values + * for options that are not provided during building the {@link ProxyConfiguration} object. To disable this behavior, + * set this value to "false". + */ + Builder useSystemPropertyValues(Boolean useSystemPropertyValues); + } /** @@ -214,8 +302,9 @@ private static final class DefaultClientProxyConfigurationBuilder implements Bui private String password; private String ntlmDomain; private String ntlmWorkstation; - private Set nonProxyHosts = new HashSet<>(); + private Set nonProxyHosts; private Boolean preemptiveBasicAuthenticationEnabled; + private Boolean useSystemPropertyValues = Boolean.TRUE; @Override public Builder endpoint(URI endpoint) { @@ -282,6 +371,9 @@ public Builder nonProxyHosts(Set nonProxyHosts) { @Override public Builder addNonProxyHost(String nonProxyHost) { + if (this.nonProxyHosts == null) { + this.nonProxyHosts = new HashSet<>(); + } this.nonProxyHosts.add(nonProxyHost); return this; } @@ -300,6 +392,16 @@ public void setPreemptiveBasicAuthenticationEnabled(Boolean preemptiveBasicAuthe preemptiveBasicAuthenticationEnabled(preemptiveBasicAuthenticationEnabled); } + @Override + public Builder useSystemPropertyValues(Boolean useSystemPropertyValues) { + this.useSystemPropertyValues = useSystemPropertyValues; + return this; + } + + public void setUseSystemPropertyValues(Boolean useSystemPropertyValues) { + useSystemPropertyValues(useSystemPropertyValues); + } + @Override public ProxyConfiguration build() { return new ProxyConfiguration(this); diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/ApacheHttpRequestConfig.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/ApacheHttpRequestConfig.java index ddcaafd6a06d..94bffbe36243 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/ApacheHttpRequestConfig.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/ApacheHttpRequestConfig.java @@ -29,6 +29,7 @@ public final class ApacheHttpRequestConfig { private final Duration socketTimeout; private final Duration connectionTimeout; + private final Duration connectionAcquireTimeout; private final InetAddress localAddress; private final boolean expectContinueEnabled; private final ProxyConfiguration proxyConfiguration; @@ -36,6 +37,7 @@ public final class ApacheHttpRequestConfig { private ApacheHttpRequestConfig(Builder builder) { this.socketTimeout = builder.socketTimeout; this.connectionTimeout = builder.connectionTimeout; + this.connectionAcquireTimeout = builder.connectionAcquireTimeout; this.localAddress = builder.localAddress; this.expectContinueEnabled = builder.expectContinueEnabled; this.proxyConfiguration = builder.proxyConfiguration; @@ -49,6 +51,10 @@ public Duration connectionTimeout() { return connectionTimeout; } + public Duration connectionAcquireTimeout() { + return connectionAcquireTimeout; + } + public InetAddress localAddress() { return localAddress; } @@ -75,6 +81,7 @@ public static final class Builder { private Duration socketTimeout; private Duration connectionTimeout; + private Duration connectionAcquireTimeout; private InetAddress localAddress; private Boolean expectContinueEnabled; private ProxyConfiguration proxyConfiguration; @@ -92,6 +99,11 @@ public Builder connectionTimeout(Duration connectionTimeout) { return this; } + public Builder connectionAcquireTimeout(Duration connectionAcquireTimeout) { + this.connectionAcquireTimeout = connectionAcquireTimeout; + return this; + } + public Builder localAddress(InetAddress localAddress) { this.localAddress = localAddress; return this; diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlanner.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlanner.java index b7b0d1b87c75..776c72d39473 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlanner.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlanner.java @@ -37,9 +37,9 @@ public class SdkProxyRoutePlanner extends DefaultRoutePlanner { private HttpHost proxy; private Set hostPatterns; - public SdkProxyRoutePlanner(String proxyHost, int proxyPort, Set nonProxyHosts) { + public SdkProxyRoutePlanner(String proxyHost, int proxyPort, String proxyProtocol, Set nonProxyHosts) { super(DefaultSchemePortResolver.INSTANCE); - proxy = new HttpHost(proxyHost, proxyPort); + proxy = new HttpHost(proxyHost, proxyPort, proxyProtocol); this.hostPatterns = nonProxyHosts; } diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/impl/ApacheHttpRequestFactory.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/impl/ApacheHttpRequestFactory.java index 3f1e3dd5030f..ff25cab05c8a 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/impl/ApacheHttpRequestFactory.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/impl/ApacheHttpRequestFactory.java @@ -65,9 +65,10 @@ private void addRequestConfig(final HttpRequestBase base, final SdkHttpFullRequest request, final ApacheHttpRequestConfig requestConfig) { final int connectTimeout = saturatedCast(requestConfig.connectionTimeout().toMillis()); + final int connectAcquireTimeout = saturatedCast(requestConfig.connectionAcquireTimeout().toMillis()); final RequestConfig.Builder requestConfigBuilder = RequestConfig .custom() - .setConnectionRequestTimeout(connectTimeout) + .setConnectionRequestTimeout(connectAcquireTimeout) .setConnectTimeout(connectTimeout) .setSocketTimeout(saturatedCast(requestConfig.socketTimeout().toMillis())) .setLocalAddress(requestConfig.localAddress()); diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/utils/ApacheUtils.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/utils/ApacheUtils.java index 845a849b3088..d7eb4e82113e 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/utils/ApacheUtils.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/utils/ApacheUtils.java @@ -86,14 +86,14 @@ private static Credentials newNtCredentials(ProxyConfiguration proxyConfiguratio * Returns a new instance of AuthScope used for proxy authentication. */ private static AuthScope newAuthScope(ProxyConfiguration proxyConfiguration) { - return new AuthScope(proxyConfiguration.endpoint().getHost(), proxyConfiguration.endpoint().getPort()); + return new AuthScope(proxyConfiguration.host(), proxyConfiguration.port()); } private static void addPreemptiveAuthenticationProxy(HttpClientContext clientContext, ProxyConfiguration proxyConfiguration) { if (proxyConfiguration.preemptiveBasicAuthenticationEnabled()) { - HttpHost targetHost = new HttpHost(proxyConfiguration.endpoint().getHost(), proxyConfiguration.endpoint().getPort()); + HttpHost targetHost = new HttpHost(proxyConfiguration.host(), proxyConfiguration.port()); final CredentialsProvider credsProvider = newProxyCredentialsProvider(proxyConfiguration); // Create AuthCache instance AuthCache authCache = new BasicAuthCache(); diff --git a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ProxyConfigurationTest.java b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ProxyConfigurationTest.java new file mode 100644 index 000000000000..f05f2df22880 --- /dev/null +++ b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ProxyConfigurationTest.java @@ -0,0 +1,115 @@ +/* + * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.apache; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import java.util.HashSet; +import java.util.Set; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +public class ProxyConfigurationTest { + + @Before + public void setup() { + clearProxyProperties(); + } + + @AfterClass + public static void cleanup() { + clearProxyProperties(); + } + + @Test + public void testEndpointValues_SystemPropertyEnabled() { + String host = "foo.com"; + int port = 7777; + System.setProperty("http.proxyHost", host); + System.setProperty("http.proxyPort", Integer.toString(port)); + + ProxyConfiguration config = ProxyConfiguration.builder().useSystemPropertyValues(true).build(); + + assertThat(config.host()).isEqualTo(host); + assertThat(config.port()).isEqualTo(port); + assertThat(config.scheme()).isNull(); + } + + @Test + public void testEndpointValues_SystemPropertyDisabled() { + ProxyConfiguration config = ProxyConfiguration.builder() + .endpoint(URI.create("http://localhost:1234")) + .useSystemPropertyValues(Boolean.FALSE) + .build(); + + assertThat(config.host()).isEqualTo("localhost"); + assertThat(config.port()).isEqualTo(1234); + assertThat(config.scheme()).isEqualTo("http"); + } + + @Test + public void testProxyConfigurationWithSystemPropertyDisabled() throws Exception { + Set nonProxyHosts = new HashSet<>(); + nonProxyHosts.add("foo.com"); + + // system property should not be used + System.setProperty("http.proxyHost", "foo.com"); + System.setProperty("http.proxyPort", "5555"); + System.setProperty("http.nonProxyHosts", "bar.com"); + System.setProperty("http.proxyUser", "user"); + + ProxyConfiguration config = ProxyConfiguration.builder() + .endpoint(URI.create("http://localhost:1234")) + .nonProxyHosts(nonProxyHosts) + .useSystemPropertyValues(Boolean.FALSE) + .build(); + + assertThat(config.host()).isEqualTo("localhost"); + assertThat(config.port()).isEqualTo(1234); + assertThat(config.nonProxyHosts()).isEqualTo(nonProxyHosts); + assertThat(config.username()).isNull(); + } + + @Test + public void testProxyConfigurationWithSystemPropertyEnabled() throws Exception { + Set nonProxyHosts = new HashSet<>(); + nonProxyHosts.add("foo.com"); + + // system property should not be used + System.setProperty("http.proxyHost", "foo.com"); + System.setProperty("http.proxyPort", "5555"); + System.setProperty("http.nonProxyHosts", "bar.com"); + System.setProperty("http.proxyUser", "user"); + + ProxyConfiguration config = ProxyConfiguration.builder() + .nonProxyHosts(nonProxyHosts) + .build(); + + assertThat(config.nonProxyHosts()).isEqualTo(nonProxyHosts); + assertThat(config.host()).isEqualTo("foo.com"); + assertThat(config.username()).isEqualTo("user"); + } + + private static void clearProxyProperties() { + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + System.clearProperty("http.nonProxyHosts"); + System.clearProperty("http.proxyUser"); + System.clearProperty("http.proxyPassword"); + } +} diff --git a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlannerTest.java b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlannerTest.java new file mode 100644 index 000000000000..9b6e77bf2a8a --- /dev/null +++ b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlannerTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.apache.internal; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; +import org.apache.http.HttpException; +import org.apache.http.HttpHost; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.junit.Test; + +/** + * Unit tests for {@link SdkProxyRoutePlanner}. + */ +public class SdkProxyRoutePlannerTest { + private static final HttpHost S3_HOST = new HttpHost("s3.us-west-2.amazonaws.com", 443, "https"); + private static final HttpGet S3_REQUEST = new HttpGet("/my-bucket/my-object"); + private static final HttpClientContext CONTEXT = new HttpClientContext(); + + @Test + public void testSetsCorrectSchemeBasedOnProcotol_HTTPS() throws HttpException { + SdkProxyRoutePlanner planner = new SdkProxyRoutePlanner("localhost", 1234, "https", Collections.emptySet()); + + HttpHost proxyHost = planner.determineRoute(S3_HOST, S3_REQUEST, CONTEXT).getProxyHost(); + assertEquals("localhost", proxyHost.getHostName()); + assertEquals("https", proxyHost.getSchemeName()); + } + + @Test + public void testSetsCorrectSchemeBasedOnProcotol_HTTP() throws HttpException { + SdkProxyRoutePlanner planner = new SdkProxyRoutePlanner("localhost", 1234, "http", Collections.emptySet()); + + HttpHost proxyHost = planner.determineRoute(S3_HOST, S3_REQUEST, CONTEXT).getProxyHost(); + assertEquals("localhost", proxyHost.getHostName()); + assertEquals("http", proxyHost.getSchemeName()); + } +} \ No newline at end of file diff --git a/utils/src/main/java/software/amazon/awssdk/utils/ProxySystemSetting.java b/utils/src/main/java/software/amazon/awssdk/utils/ProxySystemSetting.java new file mode 100644 index 000000000000..fc0ba0f6105b --- /dev/null +++ b/utils/src/main/java/software/amazon/awssdk/utils/ProxySystemSetting.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.utils; + +import software.amazon.awssdk.annotations.SdkProtectedApi; + +/** + * The system properties related to http proxy + */ +@SdkProtectedApi +public enum ProxySystemSetting implements SystemSetting { + + PROXY_HOST("http.proxyHost"), + PROXY_PORT("http.proxyPort"), + NON_PROXY_HOSTS("http.nonProxyHosts"), + PROXY_USERNAME("http.proxyUser"), + PROXY_PASSWORD("http.proxyPassword") + ; + + private final String systemProperty; + + ProxySystemSetting(String systemProperty) { + this.systemProperty = systemProperty; + } + + @Override + public String property() { + return systemProperty; + } + + @Override + public String environmentVariable() { + return null; + } + + @Override + public String defaultValue() { + return null; + } +}