Skip to content

Commit 46a9aef

Browse files
committed
Support ClientContextParams for S3CrtAsyncClient
1 parent b11e9b4 commit 46a9aef

File tree

3 files changed

+123
-8
lines changed

3 files changed

+123
-8
lines changed

services/s3/src/main/java/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.java

+21
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,27 @@ default S3CrtAsyncClientBuilder httpConfiguration(Consumer<S3CrtHttpConfiguratio
176176
.build());
177177
}
178178

179+
// S3 client context params, copied from S3BaseClientBuilder.
180+
/**
181+
* Enables this client to use S3 Transfer Acceleration endpoints.
182+
*/
183+
S3CrtAsyncClientBuilder accelerate(Boolean accelerate);
184+
185+
/**
186+
* Disables this client's usage of Multi-Region Access Points.
187+
*/
188+
S3CrtAsyncClientBuilder disableMultiRegionAccessPoints(Boolean disableMultiRegionAccessPoints);
189+
190+
/**
191+
* Forces this client to use path-style addressing for buckets.
192+
*/
193+
S3CrtAsyncClientBuilder forcePathStyle(Boolean forcePathStyle);
194+
195+
/**
196+
* Enables this client to use an ARN's region when constructing an endpoint instead of the client's configured
197+
* region.
198+
*/
199+
S3CrtAsyncClientBuilder useArnRegion(Boolean useArnRegion);
179200

180201
@Override
181202
S3AsyncClient build();

services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClient.java

+61-8
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@
2121
import static software.amazon.awssdk.services.s3.internal.crt.S3NativeClientConfiguration.DEFAULT_PART_SIZE_IN_BYTES;
2222

2323
import java.net.URI;
24+
import java.util.ArrayList;
25+
import java.util.List;
2426
import java.util.concurrent.CompletableFuture;
2527
import software.amazon.awssdk.annotations.SdkInternalApi;
28+
import software.amazon.awssdk.annotations.SdkTestInternalApi;
2629
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
2730
import software.amazon.awssdk.awscore.AwsRequest;
2831
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
2932
import software.amazon.awssdk.core.SdkRequest;
3033
import software.amazon.awssdk.core.checksums.ChecksumValidation;
34+
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
3135
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
3236
import software.amazon.awssdk.core.interceptor.Context;
3337
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
@@ -69,6 +73,19 @@ public CompletableFuture<CopyObjectResponse> copyObject(CopyObjectRequest copyOb
6973
}
7074

7175
private static S3AsyncClient initializeS3AsyncClient(DefaultS3CrtClientBuilder builder) {
76+
ClientOverrideConfiguration.Builder overrideConfigurationBuilder =
77+
ClientOverrideConfiguration.builder()
78+
.putAdvancedOption(SdkAdvancedClientOption.SIGNER, new NoOpSigner())
79+
.putExecutionAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION,
80+
ChecksumValidation.FORCE_SKIP)
81+
.retryPolicy(RetryPolicy.none())
82+
.addExecutionInterceptor(new ValidateRequestInterceptor())
83+
.addExecutionInterceptor(new AttachHttpAttributesExecutionInterceptor());
84+
85+
if (builder.executionInterceptors != null) {
86+
builder.executionInterceptors.forEach(overrideConfigurationBuilder::addExecutionInterceptor);
87+
}
88+
7289
return S3AsyncClient.builder()
7390
// Disable checksum, retry policy and signer because they are handled in crt
7491
.serviceConfiguration(S3Configuration.builder()
@@ -77,14 +94,11 @@ private static S3AsyncClient initializeS3AsyncClient(DefaultS3CrtClientBuilder b
7794
.region(builder.region)
7895
.endpointOverride(builder.endpointOverride)
7996
.credentialsProvider(builder.credentialsProvider)
80-
.overrideConfiguration(o -> o.putAdvancedOption(SdkAdvancedClientOption.SIGNER,
81-
new NoOpSigner())
82-
.putExecutionAttribute(
83-
SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION,
84-
ChecksumValidation.FORCE_SKIP)
85-
.retryPolicy(RetryPolicy.none())
86-
.addExecutionInterceptor(new ValidateRequestInterceptor())
87-
.addExecutionInterceptor(new AttachHttpAttributesExecutionInterceptor()))
97+
.overrideConfiguration(overrideConfigurationBuilder.build())
98+
.accelerate(builder.accelerate)
99+
.disableMultiRegionAccessPoints(builder.disableMultiRegionAccessPoints)
100+
.forcePathStyle(builder.forcePathStyle)
101+
.useArnRegion(builder.useArnRegion)
88102
.httpClientBuilder(initializeS3CrtAsyncHttpClient(builder))
89103
.build();
90104
}
@@ -123,6 +137,12 @@ public static final class DefaultS3CrtClientBuilder implements S3CrtAsyncClientB
123137
private URI endpointOverride;
124138
private Boolean checksumValidationEnabled;
125139
private S3CrtHttpConfiguration httpConfiguration;
140+
private Boolean accelerate;
141+
private Boolean disableMultiRegionAccessPoints;
142+
private Boolean forcePathStyle;
143+
private Boolean useArnRegion;
144+
145+
private List<ExecutionInterceptor> executionInterceptors;
126146

127147
public AwsCredentialsProvider credentialsProvider() {
128148
return credentialsProvider;
@@ -206,6 +226,39 @@ public S3CrtAsyncClientBuilder httpConfiguration(S3CrtHttpConfiguration configur
206226
return this;
207227
}
208228

229+
@Override
230+
public S3CrtAsyncClientBuilder accelerate(Boolean accelerate) {
231+
this.accelerate = accelerate;
232+
return this;
233+
}
234+
235+
@Override
236+
public S3CrtAsyncClientBuilder disableMultiRegionAccessPoints(Boolean disableMultiRegionAccessPoints) {
237+
this.disableMultiRegionAccessPoints = disableMultiRegionAccessPoints;
238+
return this;
239+
}
240+
241+
@Override
242+
public S3CrtAsyncClientBuilder forcePathStyle(Boolean forcePathStyle) {
243+
this.forcePathStyle = forcePathStyle;
244+
return this;
245+
}
246+
247+
@Override
248+
public S3CrtAsyncClientBuilder useArnRegion(Boolean useArnRegion) {
249+
this.useArnRegion = useArnRegion;
250+
return this;
251+
}
252+
253+
@SdkTestInternalApi
254+
S3CrtAsyncClientBuilder addExecutionInterceptor(ExecutionInterceptor executionInterceptor) {
255+
if (executionInterceptors == null) {
256+
this.executionInterceptors = new ArrayList<>();
257+
}
258+
executionInterceptors.add(executionInterceptor);
259+
return this;
260+
}
261+
209262
@Override
210263
public S3CrtAsyncClient build() {
211264
return new DefaultS3CrtAsyncClient(this);

services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClientTest.java

+41
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,23 @@
1515

1616
package software.amazon.awssdk.services.s3.internal.crt;
1717

18+
import static org.assertj.core.api.Assertions.assertThat;
1819
import static org.assertj.core.api.Assertions.assertThatThrownBy;
1920

21+
import java.util.concurrent.atomic.AtomicReference;
2022
import org.junit.jupiter.api.Test;
2123
import org.junit.jupiter.params.ParameterizedTest;
2224
import org.junit.jupiter.params.provider.ValueSource;
2325
import software.amazon.awssdk.auth.signer.AwsS3V4Signer;
2426
import software.amazon.awssdk.core.async.AsyncRequestBody;
2527
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
28+
import software.amazon.awssdk.core.interceptor.Context;
29+
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
30+
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
31+
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
2632
import software.amazon.awssdk.services.s3.S3AsyncClient;
33+
import software.amazon.awssdk.services.s3.endpoints.S3ClientContextParams;
34+
import software.amazon.awssdk.utils.AttributeMap;
2735

2836
class DefaultS3CrtAsyncClientTest {
2937

@@ -40,6 +48,39 @@ void requestSignerOverrideProvided_shouldThrowException() {
4048
}
4149
}
4250

51+
@Test
52+
void clientContextParamsSetOnBuilder_propagatedToInterceptors() {
53+
AtomicReference<AttributeMap> clientContexParams = new AtomicReference<>();
54+
55+
ExecutionInterceptor paramsCaptor = new ExecutionInterceptor() {
56+
@Override
57+
public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
58+
clientContexParams.set(executionAttributes.getAttribute(SdkInternalExecutionAttribute.CLIENT_CONTEXT_PARAMS));
59+
throw new RuntimeException("BOOM");
60+
}
61+
};
62+
63+
DefaultS3CrtAsyncClient.DefaultS3CrtClientBuilder builder =
64+
(DefaultS3CrtAsyncClient.DefaultS3CrtClientBuilder) S3CrtAsyncClient.builder();
65+
66+
builder.addExecutionInterceptor(paramsCaptor);
67+
68+
try (S3AsyncClient s3AsyncClient = builder.accelerate(false)
69+
.disableMultiRegionAccessPoints(true)
70+
.forcePathStyle(true)
71+
.useArnRegion(true)
72+
.build()) {
73+
74+
assertThatThrownBy(s3AsyncClient.listBuckets()::join).hasMessageContaining("BOOM");
75+
AttributeMap attributeMap = clientContexParams.get();
76+
77+
assertThat(attributeMap.get(S3ClientContextParams.ACCELERATE)).isFalse();
78+
assertThat(attributeMap.get(S3ClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS)).isTrue();
79+
assertThat(attributeMap.get(S3ClientContextParams.FORCE_PATH_STYLE)).isTrue();
80+
assertThat(attributeMap.get(S3ClientContextParams.USE_ARN_REGION)).isTrue();
81+
}
82+
}
83+
4384
@ParameterizedTest
4485
@ValueSource(longs = {0, -1L})
4586
void invalidConfig_shouldThrowException(long value) {

0 commit comments

Comments
 (0)