Skip to content

Commit 0d70dde

Browse files
getobject implementation and tests
1 parent 623c54f commit 0d70dde

File tree

2 files changed

+471
-0
lines changed

2 files changed

+471
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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+
/**
72+
* Downloads an S3 object using a presigned URL.
73+
*/
74+
@Override
75+
public <ReturnT> ReturnT getObject(PresignedUrlGetObjectRequest presignedUrlGetObjectRequest,
76+
ResponseTransformer<GetObjectResponse, ReturnT> responseTransformer)
77+
throws NoSuchKeyException, InvalidObjectStateException,
78+
AwsServiceException, SdkClientException, S3Exception {
79+
80+
HttpResponseHandler<GetObjectResponse> responseHandler = protocolFactory.createResponseHandler(
81+
GetObjectResponse::builder, new XmlOperationMetadata().withHasStreamingSuccessResponse(true));
82+
83+
HttpResponseHandler<AwsServiceException> errorResponseHandler = protocolFactory.createErrorResponseHandler();
84+
85+
PresignedUrlGetObjectRequestWrapper internalRequest = PresignedUrlGetObjectRequestWrapper.builder()
86+
.url(presignedUrlGetObjectRequest.presignedUrl())
87+
.range(presignedUrlGetObjectRequest.range())
88+
.build();
89+
90+
SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(internalRequest, this.clientConfiguration);
91+
List<MetricPublisher> metricPublishers = Optional.ofNullable(
92+
clientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS))
93+
.orElse(Collections.emptyList());
94+
MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ?
95+
NoOpMetricCollector.create() : MetricCollector.create("ApiCall");
96+
try {
97+
apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "S3");
98+
//TODO: Discuss if we need to change OPERATION_NAME as part of Surface API Review
99+
apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetObject");
100+
101+
return clientHandler.execute(
102+
new ClientExecutionParams<PresignedUrlGetObjectRequestWrapper, GetObjectResponse>()
103+
.withOperationName("PresignedUrlGetObject")
104+
.withProtocolMetadata(protocolMetadata)
105+
.withResponseHandler(responseHandler)
106+
.withErrorResponseHandler(errorResponseHandler)
107+
.withRequestConfiguration(clientConfiguration)
108+
.withInput(internalRequest)
109+
.withMetricCollector(apiCallMetricCollector)
110+
// TODO: Deprecate IS_DISCOVERED_ENDPOINT, use new SKIP_ENDPOINT_RESOLUTION for better semantics
111+
.putExecutionAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT, true)
112+
.withMarshaller(new PresignedUrlGetObjectRequestMarshaller(protocolFactory)), responseTransformer);
113+
} finally {
114+
metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()));
115+
}
116+
}
117+
118+
private SdkClientConfiguration updateSdkClientConfiguration(PresignedUrlGetObjectRequestWrapper request,
119+
SdkClientConfiguration clientConfiguration) {
120+
SdkClientConfiguration.Builder configuration = clientConfiguration.toBuilder();
121+
configuration.option(SdkAdvancedClientOption.SIGNER, new NoOpSigner());
122+
configuration.option(SIGNER_OVERRIDDEN, true);
123+
return configuration.build();
124+
}
125+
126+
}

0 commit comments

Comments
 (0)