From 1b1caa08c6bcd5e1e87232818be2bc8b6503cb23 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Tue, 1 Jul 2025 15:02:06 -0700 Subject: [PATCH 1/5] Handled Surface API review comments --- .brazil.json | 2 +- .../http/apache5/Apache5HttpClient.java | 42 ++++++++++++++++++- ...ntLocalAddressOnBuilderFunctionalTest.java | 35 ++++++++++++++++ ...calAddressRoutePlannerFunctionalTest.java} | 2 +- .../http/apache5/MetricReportingTest.java | 4 +- 5 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java rename http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/{Apache5HttpClientLocalAddressFunctionalTest.java => Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java} (94%) diff --git a/.brazil.json b/.brazil.json index 5dfd7faab8b8..2e901b2648e0 100644 --- a/.brazil.json +++ b/.brazil.json @@ -4,7 +4,7 @@ "modules": { "annotations": { "packageName": "AwsJavaSdk-Core-Annotations" }, "apache-client": { "packageName": "AwsJavaSdk-HttpClient-ApacheClient" }, - "apache5-client": { "packageName": "AwsJavaSdk-HttpClient-Apache5Client-preview" }, + "apache5-client": { "packageName": "AwsJavaSdk-HttpClient-Apache5Client-Preview" }, "arns": { "packageName": "AwsJavaSdk-Core-Arns" }, "auth": { "packageName": "AwsJavaSdk-Core-Auth" }, "auth-crt": { "packageName": "AwsJavaSdk-Core-AuthCrt" }, diff --git a/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java b/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java index 8dbb74292b55..ea7e64d8b15d 100644 --- a/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java +++ b/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java @@ -25,6 +25,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +import java.net.InetAddress; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; @@ -48,6 +49,7 @@ import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner; import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.routing.HttpRoutePlanner; @@ -57,10 +59,13 @@ import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.impl.io.HttpRequestExecutor; import org.apache.hc.core5.http.io.SocketConfig; +import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.io.CloseMode; import org.apache.hc.core5.pool.PoolStats; import org.apache.hc.core5.ssl.SSLInitializationException; @@ -108,7 +113,7 @@ @SdkPublicApi public final class Apache5HttpClient implements SdkHttpClient { - public static final String CLIENT_NAME = "Apache5"; + public static final String CLIENT_NAME = "Apache5Preview"; private static final Logger log = Logger.loggerFor(Apache5HttpClient.class); private static final HostnameVerifier DEFAULT_HOSTNAME_VERIFIER = new DefaultHostnameVerifier(); @@ -206,7 +211,12 @@ private void addProxyConfig(HttpClientBuilder builder, } if (routePlanner != null) { + if (configuration.localAddress != null) { + log.debug(() -> "localAddress configuration was ignored since Route planner was explicitly provided"); + } builder.setRoutePlanner(routePlanner); + } else if (configuration.localAddress != null) { + builder.setRoutePlanner(new LocalAddressRoutePlanner(configuration.localAddress)); } if (credentialsProvider != null) { @@ -404,6 +414,11 @@ public interface Builder extends SdkHttpClient.Builder authSchemeRegistry; private ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder().build(); + private InetAddress localAddress; private Boolean expectContinueEnabled; private HttpRoutePlanner httpRoutePlanner; private CredentialsProvider credentialsProvider; @@ -560,6 +576,16 @@ public void setProxyConfiguration(ProxyConfiguration proxyConfiguration) { proxyConfiguration(proxyConfiguration); } + @Override + public Builder localAddress(InetAddress localAddress) { + this.localAddress = localAddress; + return this; + } + + public void setLocalAddress(InetAddress localAddress) { + localAddress(localAddress); + } + @Override public Builder expectContinueEnabled(Boolean expectContinueEnabled) { this.expectContinueEnabled = expectContinueEnabled; @@ -794,4 +820,18 @@ private SocketConfig buildSocketConfig(AttributeMap standardOptions) { } } + + private static class LocalAddressRoutePlanner extends DefaultRoutePlanner { + private final InetAddress localAddress; + + LocalAddressRoutePlanner(InetAddress localAddress) { + super(DefaultSchemePortResolver.INSTANCE); + this.localAddress = localAddress; + } + + @Override + protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException { + return localAddress; + } + } } diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java new file mode 100644 index 000000000000..fd1a1310dd2a --- /dev/null +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 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.apache5; + +import java.net.InetAddress; +import java.time.Duration; +import org.junit.jupiter.api.DisplayName; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientLocalAddressFunctionalTestSuite; + +@DisplayName("Apache5 HTTP Client - Local Address Functional Tests") +class Apache5HttpClientLocalAddressOnBuilderFunctionalTest extends SdkHttpClientLocalAddressFunctionalTestSuite { + + @Override + protected SdkHttpClient createHttpClient(InetAddress localAddress, Duration connectionTimeout) { + + return Apache5HttpClient.builder() + .localAddress(localAddress) + .connectionTimeout(connectionTimeout) + .build(); + } +} diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressFunctionalTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java similarity index 94% rename from http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressFunctionalTest.java rename to http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java index f5f948574066..06d078a512a3 100644 --- a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressFunctionalTest.java +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java @@ -28,7 +28,7 @@ import software.amazon.awssdk.http.SdkHttpClientLocalAddressFunctionalTestSuite; @DisplayName("Apache5 HTTP Client - Local Address Functional Tests") -class Apache5HttpClientLocalAddressFunctionalTest extends SdkHttpClientLocalAddressFunctionalTestSuite { +class Apache5HttpClientLocalAddressRoutePlannerFunctionalTest extends SdkHttpClientLocalAddressFunctionalTestSuite { @Override protected SdkHttpClient createHttpClient(InetAddress localAddress, Duration connectionTimeout) { diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/MetricReportingTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/MetricReportingTest.java index 8437f74e8859..3c2529d697f7 100644 --- a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/MetricReportingTest.java +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/MetricReportingTest.java @@ -81,7 +81,7 @@ public void prepareRequest_callableCalled_metricsReported() throws IOException { client.prepareRequest(executeRequest).call(); MetricCollection collected = collector.collect(); - assertThat(collected.metricValues(HTTP_CLIENT_NAME)).containsExactly("Apache5"); + assertThat(collected.metricValues(HTTP_CLIENT_NAME)).containsExactly("Apache5Preview"); assertThat(collected.metricValues(LEASED_CONCURRENCY)).containsExactly(1); assertThat(collected.metricValues(PENDING_CONCURRENCY_ACQUIRES)).containsExactly(2); assertThat(collected.metricValues(AVAILABLE_CONCURRENCY)).containsExactly(3); @@ -99,7 +99,7 @@ public void prepareRequest_connectionManagerNotPooling_callableCalled_metricsRep MetricCollection collected = collector.collect(); - assertThat(collected.metricValues(HTTP_CLIENT_NAME)).containsExactly("Apache5"); + assertThat(collected.metricValues(HTTP_CLIENT_NAME)).containsExactly("Apache5Preview"); assertThat(collected.metricValues(LEASED_CONCURRENCY)).isEmpty(); assertThat(collected.metricValues(PENDING_CONCURRENCY_ACQUIRES)).isEmpty(); assertThat(collected.metricValues(AVAILABLE_CONCURRENCY)).isEmpty(); From 8f086d7b17392389db1497367854e3a97a282438 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Wed, 2 Jul 2025 10:11:45 -0700 Subject: [PATCH 2/5] Added a single test for localaddress , handled review comments --- ...5HttpClientLocalAddressFunctionalTest.java | 119 ++++++++++++++++++ ...ntLocalAddressOnBuilderFunctionalTest.java | 35 ------ ...ocalAddressRoutePlannerFunctionalTest.java | 51 -------- 3 files changed, 119 insertions(+), 86 deletions(-) create mode 100644 http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressFunctionalTest.java delete mode 100644 http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java delete mode 100644 http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressFunctionalTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressFunctionalTest.java new file mode 100644 index 000000000000..505c53219a9e --- /dev/null +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressFunctionalTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 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.apache5; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.InetAddress; +import java.time.Duration; +import org.apache.hc.client5.http.impl.DefaultSchemePortResolver; +import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner; +import org.apache.hc.client5.http.routing.HttpRoutePlanner; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.logging.log4j.Level; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientLocalAddressFunctionalTestSuite; +import software.amazon.awssdk.testutils.LogCaptor; + +/** + * Functional tests for Apache5 HTTP Client's local address binding capabilities. + * Tests three scenarios: + * 1. Local address configured via builder + * 2. Local address configured via custom route planner + * 3. Both methods used together (route planner takes precedence) + */ +@DisplayName("Apache5 HTTP Client - Local Address Functional Tests") +class Apache5HttpClientLocalAddressFunctionalTest { + + @Nested + @DisplayName("When local address is configured via builder") + class LocalAddressViaBuilderTest extends SdkHttpClientLocalAddressFunctionalTestSuite { + @Override + protected SdkHttpClient createHttpClient(InetAddress localAddress, Duration connectionTimeout) { + return Apache5HttpClient.builder() + .localAddress(localAddress) + .connectionTimeout(connectionTimeout) + .build(); + } + } + + @Nested + @DisplayName("When local address is configured via custom route planner") + class LocalAddressViaRoutePlannerTest extends SdkHttpClientLocalAddressFunctionalTestSuite { + + @Override + protected SdkHttpClient createHttpClient(InetAddress localAddress, Duration connectionTimeout) { + HttpRoutePlanner routePlanner = createLocalAddressRoutePlanner(localAddress); + return Apache5HttpClient.builder() + .httpRoutePlanner(routePlanner) + .connectionTimeout(connectionTimeout) + .build(); + } + + private HttpRoutePlanner createLocalAddressRoutePlanner(InetAddress localAddress) { + return new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE) { + @Override + protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException { + return localAddress != null ? localAddress : super.determineLocalAddress(firstHop, context); + } + }; + } + } + + @Nested + @DisplayName("When both route planner and builder local address are configured (route planner takes precedence)") + class RoutePlannerPrecedenceTest extends SdkHttpClientLocalAddressFunctionalTestSuite { + + private final InetAddress BUILDER_LOCAL_ADDRESS = InetAddress.getLoopbackAddress(); + + @Override + protected SdkHttpClient createHttpClient(InetAddress localAddress, Duration connectionTimeout) { + // The localAddress parameter will be used by the route planner + // The builder's localAddress will be overridden + HttpRoutePlanner routePlanner = createLocalAddressRoutePlanner(localAddress); + SdkHttpClient httpClient; + + try (LogCaptor logCaptor = LogCaptor.create(Level.DEBUG)) { + httpClient = Apache5HttpClient.builder() + .httpRoutePlanner(routePlanner) + .localAddress(BUILDER_LOCAL_ADDRESS) // This will be overridden by route planner + .connectionTimeout(connectionTimeout) + .build(); + + assertThat(logCaptor.loggedEvents()).anySatisfy(logEvent -> { + assertThat(logEvent.getLevel()).isEqualTo(Level.DEBUG); + assertThat(logEvent.getMessage().getFormattedMessage()) + .contains("localAddress configuration was ignored since Route planner was explicitly provided"); + }); + } + return httpClient; + } + + private HttpRoutePlanner createLocalAddressRoutePlanner(InetAddress routePlannerAddress) { + return new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE) { + @Override + protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException { + // Route planner's address takes precedence over builder's address + return routePlannerAddress != null ? routePlannerAddress : super.determineLocalAddress(firstHop, context); + } + }; + } + } +} diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java deleted file mode 100644 index fd1a1310dd2a..000000000000 --- a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressOnBuilderFunctionalTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 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.apache5; - -import java.net.InetAddress; -import java.time.Duration; -import org.junit.jupiter.api.DisplayName; -import software.amazon.awssdk.http.SdkHttpClient; -import software.amazon.awssdk.http.SdkHttpClientLocalAddressFunctionalTestSuite; - -@DisplayName("Apache5 HTTP Client - Local Address Functional Tests") -class Apache5HttpClientLocalAddressOnBuilderFunctionalTest extends SdkHttpClientLocalAddressFunctionalTestSuite { - - @Override - protected SdkHttpClient createHttpClient(InetAddress localAddress, Duration connectionTimeout) { - - return Apache5HttpClient.builder() - .localAddress(localAddress) - .connectionTimeout(connectionTimeout) - .build(); - } -} diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java deleted file mode 100644 index 06d078a512a3..000000000000 --- a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientLocalAddressRoutePlannerFunctionalTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 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.apache5; - -import java.net.InetAddress; -import java.time.Duration; -import org.apache.hc.client5.http.impl.DefaultSchemePortResolver; -import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner; -import org.apache.hc.client5.http.routing.HttpRoutePlanner; -import org.apache.hc.core5.http.HttpException; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.protocol.HttpContext; -import org.junit.jupiter.api.DisplayName; -import software.amazon.awssdk.http.SdkHttpClient; -import software.amazon.awssdk.http.SdkHttpClientLocalAddressFunctionalTestSuite; - -@DisplayName("Apache5 HTTP Client - Local Address Functional Tests") -class Apache5HttpClientLocalAddressRoutePlannerFunctionalTest extends SdkHttpClientLocalAddressFunctionalTestSuite { - - @Override - protected SdkHttpClient createHttpClient(InetAddress localAddress, Duration connectionTimeout) { - HttpRoutePlanner routePlanner = createLocalAddressRoutePlanner(localAddress); - - return Apache5HttpClient.builder() - .httpRoutePlanner(routePlanner) - .connectionTimeout(connectionTimeout) - .build(); - } - - private HttpRoutePlanner createLocalAddressRoutePlanner(InetAddress localAddress) { - return new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE) { - @Override - protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException { - return localAddress != null ? localAddress : super.determineLocalAddress(firstHop, context); - } - }; - } -} From 286b515da4b3f85c435fc974b64c1a1af59af8f3 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Wed, 2 Jul 2025 11:24:19 -0700 Subject: [PATCH 3/5] Removing internal package name as -preview after internal discussion --- .brazil.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.brazil.json b/.brazil.json index 2e901b2648e0..3b29aff0123a 100644 --- a/.brazil.json +++ b/.brazil.json @@ -4,7 +4,7 @@ "modules": { "annotations": { "packageName": "AwsJavaSdk-Core-Annotations" }, "apache-client": { "packageName": "AwsJavaSdk-HttpClient-ApacheClient" }, - "apache5-client": { "packageName": "AwsJavaSdk-HttpClient-Apache5Client-Preview" }, + "apache5-client": { "packageName": "AwsJavaSdk-HttpClient-Apache5Client" }, "arns": { "packageName": "AwsJavaSdk-Core-Arns" }, "auth": { "packageName": "AwsJavaSdk-Core-Auth" }, "auth-crt": { "packageName": "AwsJavaSdk-Core-AuthCrt" }, From 1b520dcc7e333730fce70904b10bc4ba2020c305 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Thu, 3 Jul 2025 08:39:22 -0700 Subject: [PATCH 4/5] Fix transient text case failures --- .../amazon/awssdk/http/apache/ApacheClientTlsAuthTest.java | 1 + .../amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java | 1 + 2 files changed, 2 insertions(+) diff --git a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheClientTlsAuthTest.java b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheClientTlsAuthTest.java index 113de34d8ca5..ec93b85714d7 100644 --- a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheClientTlsAuthTest.java +++ b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheClientTlsAuthTest.java @@ -83,6 +83,7 @@ public static void setUp() throws IOException { wireMockServer = new WireMockServer(wireMockConfig() .dynamicHttpsPort() + .dynamicPort() .needClientAuth(true) .keystorePath(serverKeyStore.toAbsolutePath().toString()) .keystorePassword(STORE_PASSWORD) diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java index 9203096cae9f..8d3165be6ebd 100644 --- a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java @@ -82,6 +82,7 @@ public static void setUp() throws IOException { wireMockServer = new WireMockServer(wireMockConfig() .dynamicHttpsPort() + .dynamicPort() .needClientAuth(true) .keystorePath(serverKeyStore.toAbsolutePath().toString()) .keystorePassword(STORE_PASSWORD) From 3a51be03560005803e4df9baa0daacf1d0b5df8f Mon Sep 17 00:00:00 2001 From: John Viegas Date: Mon, 7 Jul 2025 17:43:43 -0700 Subject: [PATCH 5/5] Handled comment for merge to master PR for apache 5.x --- bom-internal/pom.xml | 10 ++++++++++ http-clients/apache5-client/pom.xml | 7 ------- .../awssdk/http/apache5/Apache5HttpClient.java | 14 +++++--------- .../apache-client/reflect-config.json | 8 -------- .../http/apache5/Apache5ClientTlsAuthTest.java | 8 ++------ pom.xml | 3 ++- 6 files changed, 19 insertions(+), 31 deletions(-) diff --git a/bom-internal/pom.xml b/bom-internal/pom.xml index 3b079b684c3c..f8e88ee88c14 100644 --- a/bom-internal/pom.xml +++ b/bom-internal/pom.xml @@ -94,6 +94,16 @@ httpcore ${httpcomponents.httpcore.version} + + org.apache.httpcomponents.client5 + httpclient5 + ${httpcomponents.client5.version} + + + org.apache.httpcomponents.core5 + httpcore5 + ${httpcomponents.core5.version} + commons-codec commons-codec diff --git a/http-clients/apache5-client/pom.xml b/http-clients/apache5-client/pom.xml index c2426709da7b..46bae8e51051 100644 --- a/http-clients/apache5-client/pom.xml +++ b/http-clients/apache5-client/pom.xml @@ -43,12 +43,10 @@ org.apache.httpcomponents.client5 httpclient5 - 5.5 org.apache.httpcomponents.core5 httpcore5 - 5.3.4 software.amazon.awssdk @@ -110,11 +108,6 @@ assertj-core test - - org.hamcrest - hamcrest-all - test - com.github.tomakehurst wiremock-jre8 diff --git a/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java b/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java index ea7e64d8b15d..135b76e05a0d 100644 --- a/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java +++ b/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/Apache5HttpClient.java @@ -113,7 +113,7 @@ @SdkPublicApi public final class Apache5HttpClient implements SdkHttpClient { - public static final String CLIENT_NAME = "Apache5Preview"; + private static final String CLIENT_NAME = "Apache5Preview"; private static final Logger log = Logger.loggerFor(Apache5HttpClient.class); private static final HostnameVerifier DEFAULT_HOSTNAME_VERIFIER = new DefaultHostnameVerifier(); @@ -733,14 +733,10 @@ public PoolingHttpClientConnectionManager create(Apache5HttpClient.DefaultBuilde // Skip TTL=0 to maintain backward compatibility (infinite in 4.x vs immediate expiration in 5.x) builder.setConnectionTimeToLive(TimeValue.of(connectionTtl.toMillis(), TimeUnit.MILLISECONDS)); } - PoolingHttpClientConnectionManager cm = builder.build(); - - - cm.setDefaultMaxPerRoute(standardOptions.get(SdkHttpConfigurationOption.MAX_CONNECTIONS)); - cm.setMaxTotal(standardOptions.get(SdkHttpConfigurationOption.MAX_CONNECTIONS)); - cm.setDefaultSocketConfig(buildSocketConfig(standardOptions)); - - return cm; + builder.setMaxConnPerRoute(standardOptions.get(SdkHttpConfigurationOption.MAX_CONNECTIONS)); + builder.setMaxConnTotal(standardOptions.get(SdkHttpConfigurationOption.MAX_CONNECTIONS)); + builder.setDefaultSocketConfig(buildSocketConfig(standardOptions)); + return builder.build(); } private SSLConnectionSocketFactory getPreferredSocketFactory(Apache5HttpClient.DefaultBuilder configuration, diff --git a/http-clients/apache5-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/apache-client/reflect-config.json b/http-clients/apache5-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/apache-client/reflect-config.json index ce80a77b59d4..cae8832dd42d 100644 --- a/http-clients/apache5-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/apache-client/reflect-config.json +++ b/http-clients/apache5-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/apache-client/reflect-config.json @@ -8,14 +8,6 @@ } ] }, - { - "name": "org.apache.http.client.config.RequestConfig$Builder", - "methods": [ - { - "name": "setNormalizeUri" - } - ] - }, { "name": "org.apache.commons.logging.LogFactory", "allDeclaredConstructors": true, diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java index 8d3165be6ebd..45e4b44a6d59 100644 --- a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ClientTlsAuthTest.java @@ -20,8 +20,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.instanceOf; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.utils.JavaSystemSetting.SSL_KEY_STORE; import static software.amazon.awssdk.utils.JavaSystemSetting.SSL_KEY_STORE_PASSWORD; import static software.amazon.awssdk.utils.JavaSystemSetting.SSL_KEY_STORE_TYPE; @@ -37,8 +36,6 @@ import javax.net.ssl.SSLException; import org.apache.hc.client5.http.socket.ConnectionSocketFactory; import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; -import org.apache.hc.core5.http.NoHttpResponseException; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -126,9 +123,8 @@ public void canMakeHttpsRequestWhenKeyProviderConfigured() throws IOException { @Test public void requestFailsWhenKeyProviderNotConfigured() throws IOException { - thrown.expect(anyOf(instanceOf(NoHttpResponseException.class), instanceOf(SSLException.class), instanceOf(SocketException.class))); client = Apache5HttpClient.builder().tlsKeyManagersProvider(NoneTlsKeyManagersProvider.getInstance()).build(); - makeRequestWithHttpClient(client); + assertThatThrownBy(() -> makeRequestWithHttpClient(client)).isInstanceOfAny(SSLException.class, SocketException.class); } @Test diff --git a/pom.xml b/pom.xml index 40b7605f53a2..5dc9ded7fa62 100644 --- a/pom.xml +++ b/pom.xml @@ -183,7 +183,8 @@ 1.8 4.5.13 4.4.16 - + 5.5 + 5.3.4 1.0.4