Skip to content

Commit 1d69ae4

Browse files
committed
Reuse checksum on streaming request retries
1 parent bd9e3be commit 1d69ae4

File tree

3 files changed

+34
-8
lines changed

3 files changed

+34
-8
lines changed

src/aws-cpp-sdk-core/include/aws/core/AmazonWebServiceRequest.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ namespace Aws
3535
typedef std::function<void(const AmazonWebServiceRequest&)> RequestRetryHandler;
3636
typedef std::function<void(const Aws::Http::HttpRequest&)> RequestSignedHandler;
3737

38+
struct RetryContext {
39+
std::pair<Aws::String, std::shared_ptr<Aws::Utils::Crypto::Hash>> m_requestHash;
40+
};
41+
3842
/**
3943
* Base level abstraction for all modeled AWS requests
4044
*/
@@ -222,7 +226,9 @@ namespace Aws
222226
*/
223227
Aws::Set<Aws::Client::UserAgentFeature> GetUserAgentFeatures() const { return m_userAgentFeatures; }
224228

225-
inline virtual bool RequestChecksumRequired() const { return false; }
229+
inline virtual bool RequestChecksumRequired() const { return false; }
230+
231+
mutable Aws::RetryContext m_retryContext;
226232
protected:
227233
/**
228234
* Default does nothing. Override this to convert what would otherwise be the payload of the

src/aws-cpp-sdk-core/include/smithy/client/features/ChecksumInterceptor.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,42 +84,49 @@ class ChecksumInterceptor : public smithy::interceptor::Interceptor {
8484
// AwsAuthSigner decide it.
8585
if (request.IsStreaming() && checksumValueAndAlgorithmProvided) {
8686
addChecksumFeatureForChecksumName(checksumAlgorithmName, request);
87-
const auto hash = Aws::MakeShared<PrecalculatedHash>(AWS_SMITHY_CLIENT_CHECKSUM, checksumHeader->second);
88-
httpRequest->SetRequestHash(checksumAlgorithmName, hash);
87+
if (httpRequest->GetRequestHash().second == nullptr) {
88+
const auto hash = Aws::MakeShared<PrecalculatedHash>(AWS_SMITHY_CLIENT_CHECKSUM, checksumHeader->second);
89+
httpRequest->SetRequestHash(checksumAlgorithmName, hash);
90+
}
8991
} else if (checksumValueAndAlgorithmProvided) {
9092
httpRequest->SetHeaderValue(checksumType, checksumHeader->second);
9193
} else if (checksumAlgorithmName == "crc64nvme") {
9294
request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC64);
9395
if (request.IsStreaming()) {
94-
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<CRC64>(AWS_SMITHY_CLIENT_CHECKSUM));
96+
if (httpRequest->GetRequestHash().second == nullptr)
97+
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<CRC64>(AWS_SMITHY_CLIENT_CHECKSUM));
9598
} else {
9699
httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateCRC64(*(GetBodyStream(request)))));
97100
}
98101
} else if (checksumAlgorithmName == "crc32") {
99102
request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32);
100103
if (request.IsStreaming()) {
101-
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<CRC32>(AWS_SMITHY_CLIENT_CHECKSUM));
104+
if (httpRequest->GetRequestHash().second == nullptr)
105+
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<CRC32>(AWS_SMITHY_CLIENT_CHECKSUM));
102106
} else {
103107
httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateCRC32(*(GetBodyStream(request)))));
104108
}
105109
} else if (checksumAlgorithmName == "crc32c") {
106110
request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C);
107111
if (request.IsStreaming()) {
108-
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<CRC32C>(AWS_SMITHY_CLIENT_CHECKSUM));
112+
if (httpRequest->GetRequestHash().second == nullptr)
113+
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<CRC32C>(AWS_SMITHY_CLIENT_CHECKSUM));
109114
} else {
110115
httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateCRC32C(*(GetBodyStream(request)))));
111116
}
112117
} else if (checksumAlgorithmName == "sha256") {
113118
request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA256);
114119
if (request.IsStreaming()) {
115-
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<Sha256>(AWS_SMITHY_CLIENT_CHECKSUM));
120+
if (httpRequest->GetRequestHash().second == nullptr)
121+
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<Sha256>(AWS_SMITHY_CLIENT_CHECKSUM));
116122
} else {
117123
httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateSHA256(*(GetBodyStream(request)))));
118124
}
119125
} else if (checksumAlgorithmName == "sha1") {
120126
request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA1);
121127
if (request.IsStreaming()) {
122-
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<Sha1>(AWS_SMITHY_CLIENT_CHECKSUM));
128+
if (httpRequest->GetRequestHash().second == nullptr)
129+
httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared<Sha1>(AWS_SMITHY_CLIENT_CHECKSUM));
123130
} else {
124131
httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateSHA1(*(GetBodyStream(request)))));
125132
}

src/aws-cpp-sdk-core/source/client/AWSClient.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,13 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri,
389389
{
390390
newUri.SetAuthority(newEndpoint);
391391
}
392+
393+
// Save checksum information from the original request if we haven't already - safe to assume that the checksum has been finalized, since we have sent and received a response
394+
if (request.m_retryContext.m_requestHash.second == nullptr) {
395+
auto originalRequestHash = httpRequest->GetRequestHash();
396+
request.m_retryContext.m_requestHash = originalRequestHash;
397+
}
398+
392399
httpRequest = CreateHttpRequest(newUri, method, request.GetResponseStreamFactory());
393400

394401
httpRequest->SetHeaderValue(Http::SDK_INVOCATION_ID_HEADER, invocationId);
@@ -920,6 +927,12 @@ void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, co
920927
httpRequest->SetContinueRequestHandle(request.GetContinueRequestHandler());
921928
httpRequest->SetServiceSpecificParameters(request.GetServiceSpecificParameters());
922929
request.AddQueryStringParameters(httpRequest->GetUri());
930+
931+
// check for retry context, if present use it
932+
if (request.m_retryContext.m_requestHash.second != nullptr) {
933+
const auto hash = Aws::MakeShared<Aws::Utils::Crypto::PrecalculatedHash>(AWS_SMITHY_CLIENT_CHECKSUM, HashingUtils::Base64Encode(request.m_retryContext.m_requestHash.second->GetHash().GetResult()));
934+
httpRequest->SetRequestHash(request.m_retryContext.m_requestHash.first, hash);
935+
}
923936
}
924937

925938
Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, long long expirationInSeconds, const std::shared_ptr<Aws::Http::ServiceSpecificParameters> serviceSpecificParameter)

0 commit comments

Comments
 (0)