Skip to content

Commit 2a32b57

Browse files
Add DefaultPresignedUrlManager getObject implementation for S3 pre-signed URL (#6241)
* getobject implementation and tests * corrected the getObject params in test: * fixed build failure-dependency issue with Retrystrategy in test * fixed sonarcube issues * addressed sonarcube issue * edited javadocs, added invalidurl test
1 parent 623c54f commit 2a32b57

File tree

2 files changed

+500
-0
lines changed

2 files changed

+500
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.s3.internal.presignedurl;
17+
18+
import static software.amazon.awssdk.core.client.config.SdkClientOption.SIGNER_OVERRIDDEN;
19+
20+
import java.util.Collections;
21+
import java.util.List;
22+
import java.util.Optional;
23+
import software.amazon.awssdk.annotations.SdkInternalApi;
24+
import software.amazon.awssdk.awscore.exception.AwsServiceException;
25+
import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata;
26+
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
27+
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
28+
import software.amazon.awssdk.core.client.config.SdkClientOption;
29+
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
30+
import software.amazon.awssdk.core.client.handler.SyncClientHandler;
31+
import software.amazon.awssdk.core.exception.SdkClientException;
32+
import software.amazon.awssdk.core.http.HttpResponseHandler;
33+
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
34+
import software.amazon.awssdk.core.metrics.CoreMetric;
35+
import software.amazon.awssdk.core.signer.NoOpSigner;
36+
import software.amazon.awssdk.core.sync.ResponseTransformer;
37+
import software.amazon.awssdk.metrics.MetricCollector;
38+
import software.amazon.awssdk.metrics.MetricPublisher;
39+
import software.amazon.awssdk.metrics.NoOpMetricCollector;
40+
import software.amazon.awssdk.protocols.xml.AwsS3ProtocolFactory;
41+
import software.amazon.awssdk.protocols.xml.XmlOperationMetadata;
42+
import software.amazon.awssdk.services.s3.internal.presignedurl.model.PresignedUrlGetObjectRequestWrapper;
43+
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
44+
import software.amazon.awssdk.services.s3.model.InvalidObjectStateException;
45+
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
46+
import software.amazon.awssdk.services.s3.model.S3Exception;
47+
import software.amazon.awssdk.services.s3.presignedurl.PresignedUrlManager;
48+
import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlGetObjectRequest;
49+
50+
/**
51+
* Default implementation of {@link PresignedUrlManager} for executing S3 operations using presigned URLs.
52+
*/
53+
@SdkInternalApi
54+
public final class DefaultPresignedUrlManager implements PresignedUrlManager {
55+
56+
private final SyncClientHandler clientHandler;
57+
private final AwsS3ProtocolFactory protocolFactory;
58+
private final SdkClientConfiguration clientConfiguration;
59+
private final AwsProtocolMetadata protocolMetadata;
60+
61+
public DefaultPresignedUrlManager(SyncClientHandler clientHandler,
62+
AwsS3ProtocolFactory protocolFactory,
63+
SdkClientConfiguration clientConfiguration,
64+
AwsProtocolMetadata protocolMetadata) {
65+
this.clientHandler = clientHandler;
66+
this.protocolFactory = protocolFactory;
67+
this.clientConfiguration = clientConfiguration;
68+
this.protocolMetadata = protocolMetadata;
69+
}
70+
71+
@Override
72+
public <ReturnT> ReturnT getObject(PresignedUrlGetObjectRequest presignedUrlGetObjectRequest,
73+
ResponseTransformer<GetObjectResponse, ReturnT> responseTransformer)
74+
throws NoSuchKeyException, InvalidObjectStateException,
75+
AwsServiceException, SdkClientException, S3Exception {
76+
77+
HttpResponseHandler<GetObjectResponse> responseHandler = protocolFactory.createResponseHandler(
78+
GetObjectResponse::builder, new XmlOperationMetadata().withHasStreamingSuccessResponse(true));
79+
80+
HttpResponseHandler<AwsServiceException> errorResponseHandler = protocolFactory.createErrorResponseHandler();
81+
82+
PresignedUrlGetObjectRequestWrapper internalRequest = PresignedUrlGetObjectRequestWrapper.builder()
83+
.url(presignedUrlGetObjectRequest.presignedUrl())
84+
.range(presignedUrlGetObjectRequest.range())
85+
.build();
86+
87+
SdkClientConfiguration updatedClientConfiguration = updateSdkClientConfiguration(this.clientConfiguration);
88+
List<MetricPublisher> metricPublishers = Optional.ofNullable(
89+
updatedClientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS))
90+
.orElse(Collections.emptyList());
91+
MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ?
92+
NoOpMetricCollector.create() : MetricCollector.create("ApiCall");
93+
try {
94+
apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "S3");
95+
//TODO: Discuss if we need to change OPERATION_NAME as part of Surface API Review
96+
apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetObject");
97+
98+
return clientHandler.execute(
99+
new ClientExecutionParams<PresignedUrlGetObjectRequestWrapper, GetObjectResponse>()
100+
.withOperationName("PresignedUrlGetObject")
101+
.withProtocolMetadata(protocolMetadata)
102+
.withResponseHandler(responseHandler)
103+
.withErrorResponseHandler(errorResponseHandler)
104+
.withRequestConfiguration(updatedClientConfiguration)
105+
.withInput(internalRequest)
106+
.withMetricCollector(apiCallMetricCollector)
107+
// TODO: Deprecate IS_DISCOVERED_ENDPOINT, use new SKIP_ENDPOINT_RESOLUTION for better semantics
108+
.putExecutionAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT, true)
109+
.withMarshaller(new PresignedUrlGetObjectRequestMarshaller(protocolFactory)), responseTransformer);
110+
} finally {
111+
metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()));
112+
}
113+
}
114+
115+
private SdkClientConfiguration updateSdkClientConfiguration(SdkClientConfiguration clientConfiguration) {
116+
SdkClientConfiguration.Builder configBuilder = clientConfiguration.toBuilder();
117+
configBuilder.option(SdkAdvancedClientOption.SIGNER, new NoOpSigner());
118+
configBuilder.option(SIGNER_OVERRIDDEN, true);
119+
return configBuilder.build();
120+
}
121+
122+
}

0 commit comments

Comments
 (0)