From 83243c66204048810e88fe17fe3bea4874cb3571 Mon Sep 17 00:00:00 2001 From: jencymaryjoseph <35571282+jencymaryjoseph@users.noreply.github.com> Date: Sun, 21 Jun 2026 08:37:54 -0700 Subject: [PATCH] refactor(core): Deprecate IS_DISCOVERED_ENDPOINT, add SKIP_ENDPOINT_RESOLUTION Introduce SKIP_ENDPOINT_RESOLUTION execution attribute with proper semantics for skipping endpoint resolution. The existing IS_DISCOVERED_ENDPOINT attribute was tied to the endpoint discovery feature and was being misused for pre-signed URL operations. - Deprecate IS_DISCOVERED_ENDPOINT in SdkInternalExecutionAttribute - Add SKIP_ENDPOINT_RESOLUTION attribute - Migrate BaseClientHandler to use new attribute - Add skipEndpointResolution() utility with OR fallback for backward compatibility with external consumers of the old attribute - Update codegen interceptors to use skipEndpointResolution() - Update DefaultAsyncPresignedUrlExtension to use new attribute sim: https://taskei.amazon.dev/tasks/JAVA-8374 --- .../poet/rules/EndpointResolverInterceptorSpec.java | 4 ++-- .../poet/rules/RequestEndpointInterceptorSpec.java | 4 ++-- .../rules/AwsEndpointProviderUtils.java.resource | 13 +++++++++++++ .../rules/endpoint-resolve-interceptor-preSra.java | 2 +- ...resolve-interceptor-with-endpointsbasedauth.java | 2 +- ...nt-resolve-interceptor-with-multiauthsigv4a.java | 2 +- ...dpoint-resolve-interceptor-with-stringarray.java | 2 +- .../poet/rules/endpoint-resolve-interceptor.java | 2 +- .../rules/request-set-endpoint-interceptor.java | 2 +- .../interceptor/SdkInternalExecutionAttribute.java | 12 ++++++++++++ .../core/internal/handler/BaseClientHandler.java | 2 +- .../DefaultAsyncPresignedUrlExtension.java | 3 +-- .../AwsEndpointProviderUtilsTest.java | 7 +++++++ 13 files changed, 44 insertions(+), 13 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java index 57d861ebb025..fccd4ac72f1a 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java @@ -172,8 +172,8 @@ private MethodSpec modifyRequestMethod(String endpointAuthSchemeStrategyFieldNam String providerVar = "provider"; b.addStatement("$T result = context.request()", SdkRequest.class); - // We skip resolution if the source of the endpoint is the endpoint discovery call - b.beginControlFlow("if ($1T.endpointIsDiscovered(executionAttributes))", + // We skip resolution if endpoint resolution should be skipped (e.g., endpoint discovery or pre-signed URLs) + b.beginControlFlow("if ($1T.skipEndpointResolution(executionAttributes))", endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils")); b.addStatement("return result"); b.endControlFlow(); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RequestEndpointInterceptorSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RequestEndpointInterceptorSpec.java index 63b5133f180e..c817afddded2 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RequestEndpointInterceptorSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RequestEndpointInterceptorSpec.java @@ -64,8 +64,8 @@ private MethodSpec modifyHttpRequestMethod() { .addParameter(ExecutionAttributes.class, "executionAttributes"); - // We skip setting the endpoint here if the source of the endpoint is the endpoint discovery call - b.beginControlFlow("if ($1T.endpointIsDiscovered(executionAttributes))", + // We skip setting the endpoint here if endpoint resolution should be skipped + b.beginControlFlow("if ($1T.skipEndpointResolution(executionAttributes))", endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils")) .addStatement("return context.httpRequest()") .endControlFlow().build(); diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource index 1d0fedb9f7ff..6da6c020b9bb 100644 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource +++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource @@ -66,11 +66,24 @@ public final class AwsEndpointProviderUtils { /** * True if the the {@link SdkInternalExecutionAttribute#IS_DISCOVERED_ENDPOINT} attribute is present and its value * is {@code true}, {@code false} otherwise. + * + * @deprecated Use {@link #skipEndpointResolution(ExecutionAttributes)} instead. */ + @Deprecated public static boolean endpointIsDiscovered(ExecutionAttributes attrs) { return attrs.getOptionalAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT).orElse(false); } + /** + * True if endpoint resolution should be skipped for the current request. This returns {@code true} if either + * {@link SdkInternalExecutionAttribute#SKIP_ENDPOINT_RESOLUTION} or + * {@link SdkInternalExecutionAttribute#IS_DISCOVERED_ENDPOINT} is set to {@code true}. + */ + public static boolean skipEndpointResolution(ExecutionAttributes attrs) { + return attrs.getOptionalAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION).orElse(false) + || attrs.getOptionalAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT).orElse(false); + } + /** * True if the the {@link SdkInternalExecutionAttribute#DISABLE_HOST_PREFIX_INJECTION} attribute is present and its * value is {@code true}, {@code false} otherwise. diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java index e40fb151f74f..de8be3aa52a1 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java @@ -62,7 +62,7 @@ public QueryResolveEndpointInterceptor() { @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java index 116ad513318d..71cd3af7868b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java @@ -50,7 +50,7 @@ public final class QueryResolveEndpointInterceptor implements ExecutionIntercept @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java index dd81bd471965..26e225ab6fc5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java @@ -39,7 +39,7 @@ public final class DatabaseResolveEndpointInterceptor implements ExecutionInterc @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } DatabaseEndpointProvider provider = (DatabaseEndpointProvider) executionAttributes diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java index fc8471b3bb4b..23ba5b360972 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java @@ -41,7 +41,7 @@ public final class SampleSvcResolveEndpointInterceptor implements ExecutionInter @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } SampleSvcEndpointProvider provider = (SampleSvcEndpointProvider) executionAttributes diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java index 547cbaca685f..1d170e6413e8 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java @@ -50,7 +50,7 @@ public final class QueryResolveEndpointInterceptor implements ExecutionIntercept @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java index 4cfeedb59e46..8895321a6863 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java @@ -14,7 +14,7 @@ public final class QueryRequestSetEndpointInterceptor implements ExecutionInterceptor { @Override public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return context.httpRequest(); } Endpoint endpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java index 529e129e18cd..ede315cbc114 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java @@ -125,10 +125,22 @@ public final class SdkInternalExecutionAttribute extends SdkExecutionAttribute { /** * Whether the endpoint on the request is the result of Endpoint Discovery. + * + * @deprecated This attribute is specific to the endpoint discovery feature and should not be used to skip endpoint + * resolution; use {@link #SKIP_ENDPOINT_RESOLUTION} instead. */ + @Deprecated public static final ExecutionAttribute IS_DISCOVERED_ENDPOINT = new ExecutionAttribute<>("IsDiscoveredEndpoint"); + /** + * Whether endpoint resolution should be skipped for the current request. When set to {@code true}, the SDK will not + * invoke the endpoint provider and will use the endpoint already set on the request. This is used for pre-signed URL + * operations and other scenarios where the endpoint is already fully resolved. + */ + public static final ExecutionAttribute SKIP_ENDPOINT_RESOLUTION = + new ExecutionAttribute<>("SkipEndpointResolution"); + /** * The nano time that the current API call attempt began. */ diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java index 9aea1f328993..a786ee1574af 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java @@ -96,7 +96,7 @@ private static SdkHttpFullRequest modifyEndpointHostIfNeeded(SdkHttpFullRequest ClientExecutionParams executionParams) { if (executionParams.discoveredEndpoint() != null) { URI discoveredEndpoint = executionParams.discoveredEndpoint(); - executionParams.putExecutionAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT, true); + executionParams.putExecutionAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION, true); return originalRequest.toBuilder().host(discoveredEndpoint.getHost()).port(discoveredEndpoint.getPort()).build(); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtension.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtension.java index d2a7088aa865..1fcefcd98b9a 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtension.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtension.java @@ -135,8 +135,7 @@ public CompletableFuture getObject( .withRequestConfiguration(clientConfiguration) .withInput(internalRequest) .withMetricCollector(apiCallMetricCollector) - // TODO: Deprecate IS_DISCOVERED_ENDPOINT, use new SKIP_ENDPOINT_RESOLUTION for better semantics - .putExecutionAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT, true) + .putExecutionAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION, true) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM, checksumConfigForUrl(presignedUrlDownloadRequest.presignedUrl())) .withMarshaller(new PresignedUrlDownloadRequestMarshaller(protocolFactory)), diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/AwsEndpointProviderUtilsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/AwsEndpointProviderUtilsTest.java index 83d9d1d0fb59..64bfcc897a4f 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/AwsEndpointProviderUtilsTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/AwsEndpointProviderUtilsTest.java @@ -66,6 +66,13 @@ public void endpointIsDiscovered_attrIsTrue_returnsTrue() { assertThat(AwsEndpointProviderUtils.endpointIsDiscovered(attrs)).isTrue(); } + @Test + public void skipEndpointResolution_skipAttrIsTrue_returnsTrue() { + ExecutionAttributes attrs = new ExecutionAttributes(); + attrs.putAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION, true); + assertThat(AwsEndpointProviderUtils.skipEndpointResolution(attrs)).isTrue(); + } + @Test public void disableHostPrefixInjection_attrIsFalse_returnsFalse() { ExecutionAttributes attrs = new ExecutionAttributes();