diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java index cf74d712bc26..9f6f7548cfd7 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java @@ -34,7 +34,6 @@ import software.amazon.awssdk.awscore.client.config.AwsAdvancedClientOption; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.defaultsmode.DefaultsMode; -import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.awscore.endpoint.DualstackEnabledProvider; import software.amazon.awssdk.awscore.endpoint.FipsEnabledProvider; import software.amazon.awssdk.awscore.eventstream.EventStreamInitialRequestInterceptor; @@ -75,6 +74,7 @@ import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Pair; import software.amazon.awssdk.utils.StringUtils; +import software.amazon.awssdk.utils.Validate; /** * An SDK-internal implementation of the methods in {@link AwsClientBuilder}, {@link AwsAsyncClientBuilder} and @@ -97,7 +97,6 @@ public abstract class AwsDefaultClientBuilder implements AwsClientBuilder { private static final Logger log = Logger.loggerFor(AwsClientBuilder.class); - private static final String DEFAULT_ENDPOINT_PROTOCOL = "https"; private static final String[] FIPS_SEARCH = {"fips-", "-fips"}; private static final String[] FIPS_REPLACE = {"", ""}; @@ -188,7 +187,6 @@ private SdkClientConfiguration finalizeAwsConfiguration(SdkClientConfiguration c this::resolveCredentialsIdentityProvider) // Set CREDENTIALS_PROVIDER, because older clients may be relying on it .lazyOptionIfAbsent(AwsClientOption.CREDENTIALS_PROVIDER, this::resolveCredentialsProvider) - .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, this::resolveClientEndpointProvider) // Set ENDPOINT and ENDPOINT_OVERRIDDEN, because older clients may be relying on it .lazyOptionIfAbsent(SdkClientOption.ENDPOINT, this::resolveEndpoint) .lazyOptionIfAbsent(SdkClientOption.ENDPOINT_OVERRIDDEN, this::resolveEndpointOverridden) @@ -320,33 +318,12 @@ private Region resolveSigningRegion(LazyValueSource config) { .signingRegion(config.get(AwsClientOption.AWS_REGION)); } - /** - * Specify the client endpoint provider to use for the client, if the client didn't specify one itself. - *

- * This is only used for older client versions. Newer clients specify this value themselves. - */ - private ClientEndpointProvider resolveClientEndpointProvider(LazyValueSource config) { - ServiceMetadataAdvancedOption useGlobalS3EndpointProperty = - ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT; - return AwsClientEndpointProvider.builder() - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol(DEFAULT_ENDPOINT_PROTOCOL) - .region(config.get(AwsClientOption.AWS_REGION)) - .profileFile(config.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(config.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(useGlobalS3EndpointProperty, - config.get(useGlobalS3EndpointProperty)) - .dualstackEnabled(config.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) - .fipsEnabled(config.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)) - .build(); - } - /** * Resolve the client endpoint. This code is only needed by old SDK client versions. Newer SDK client versions resolve this * information from the client endpoint provider. */ private URI resolveEndpoint(LazyValueSource config) { - return config.get(SdkClientOption.CLIENT_ENDPOINT_PROVIDER).clientEndpoint(); + return requireClientEndpointProvider(config).clientEndpoint(); } /** @@ -354,7 +331,16 @@ private URI resolveEndpoint(LazyValueSource config) { * client versions resolve this information from the client endpoint provider. */ private boolean resolveEndpointOverridden(LazyValueSource config) { - return config.get(SdkClientOption.CLIENT_ENDPOINT_PROVIDER).isEndpointOverridden(); + return requireClientEndpointProvider(config).isEndpointOverridden(); + } + + private ClientEndpointProvider requireClientEndpointProvider(LazyValueSource config) { + ClientEndpointProvider clientEndpointProvider = config.get(SdkClientOption.CLIENT_ENDPOINT_PROVIDER); + Validate.notNull(clientEndpointProvider, + "No CLIENT_ENDPOINT_PROVIDER was configured. This is typically caused by using " + + "an older service client version with a newer sdk-core. " + + "Please align all SDK dependency versions."); + return clientEndpointProvider; } /** diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java index 2e660f06ea08..7251ce6cbe1f 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java @@ -480,6 +480,13 @@ public Builder putAdvancedOption(ServiceMetadataAdvancedOption option, T return this; } + /** + * @deprecated Since 2.x.x. Use {@link #resolveFromOverrides()} instead, combined with the service's + * EndpointProvider for default endpoint resolution. This method triggers expensive + * {@code ServiceMetadata} initialization which is unnecessary when the service + * EndpointProvider can resolve the default endpoint directly. + */ + @Deprecated public AwsClientEndpointProvider build() { return new AwsClientEndpointProvider(this); } diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java index 74d263c68f43..bbd0852bf4e1 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java @@ -52,6 +52,7 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy; import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.http.SdkHttpClient; @@ -403,6 +404,17 @@ protected TestClient buildClient() { return new TestClient(super.syncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; @@ -444,6 +456,17 @@ protected TestAsyncClient buildClient() { return new TestAsyncClient(super.asyncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java index 2b9ea42a5d73..37bfd4dcf901 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java @@ -37,6 +37,10 @@ import software.amazon.awssdk.awscore.internal.defaultsmode.DefaultsModeConfiguration; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import java.net.URI; import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.http.SdkHttpClient; @@ -187,6 +191,17 @@ protected TestClient buildClient() { return new TestClient(super.syncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; @@ -220,6 +235,17 @@ protected TestAsyncClient buildClient() { return new TestAsyncClient(super.asyncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java index c20f3d924157..5cf5c5d859e7 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java @@ -22,6 +22,7 @@ import static software.amazon.awssdk.awscore.client.config.AwsAdvancedClientOption.ENABLE_DEFAULT_REGION_DETECTION; import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.SIGNER; +import java.net.URI; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -30,8 +31,10 @@ import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpConfigurationOption; @@ -122,6 +125,17 @@ protected TestClient buildClient() { return new TestClient(super.syncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java index 5c411276e923..6de908763b03 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java @@ -28,6 +28,9 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.core.SdkSystemSetting; +import java.net.URI; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.http.SdkHttpClient; @@ -159,5 +162,16 @@ protected TestClient buildClient() { return new TestClient(config); } + + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } } } diff --git a/test/old-client-version-compatibility-test/pom.xml b/test/old-client-version-compatibility-test/pom.xml index cbbb76f723c8..be3f73ee59f6 100644 --- a/test/old-client-version-compatibility-test/pom.xml +++ b/test/old-client-version-compatibility-test/pom.xml @@ -103,7 +103,7 @@ software.amazon.awssdk s3 - 2.20.136 + 2.28.1