diff --git a/src/aws-cpp-sdk-core/include/aws/core/AmazonWebServiceRequest.h b/src/aws-cpp-sdk-core/include/aws/core/AmazonWebServiceRequest.h index 2feab0e56ce..2b2a9e13c7d 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/AmazonWebServiceRequest.h +++ b/src/aws-cpp-sdk-core/include/aws/core/AmazonWebServiceRequest.h @@ -214,7 +214,7 @@ namespace Aws * Adds a used feature to the user agent string for the request. * @param feature the feature to be added in the user agent string. */ - void AddUserAgentFeature(Aws::Client::UserAgentFeature feature) { m_userAgentFeatures.insert(feature); } + void AddUserAgentFeature(Aws::Client::UserAgentFeature feature) const { m_userAgentFeatures.insert(feature); } /** * Gets all features that would be included in the requests user agent string. @@ -241,7 +241,7 @@ namespace Aws RequestSignedHandler m_onRequestSigned; RequestRetryHandler m_requestRetryHandler; mutable std::shared_ptr m_serviceSpecificParameters; - Aws::Set m_userAgentFeatures; + mutable Aws::Set m_userAgentFeatures; }; } // namespace Aws diff --git a/src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h b/src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h index 14ddf03cca5..70e83c178cb 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h +++ b/src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h @@ -17,6 +17,15 @@ enum class UserAgentFeature { S3_TRANSFER, S3_CRYPTO_V1N, S3_CRYPTO_V2, + FLEXIBLE_CHECKSUMS_REQ_CRC32, + FLEXIBLE_CHECKSUMS_REQ_CRC32C, + FLEXIBLE_CHECKSUMS_REQ_CRC64, + FLEXIBLE_CHECKSUMS_REQ_SHA1, + FLEXIBLE_CHECKSUMS_REQ_SHA256, + FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED, + FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED, + FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED, + FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED, }; class AWS_CORE_API UserAgent { diff --git a/src/aws-cpp-sdk-core/include/smithy/client/features/ChecksumInterceptor.h b/src/aws-cpp-sdk-core/include/smithy/client/features/ChecksumInterceptor.h index ba25285bb4d..e07f86fcbc7 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/features/ChecksumInterceptor.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/features/ChecksumInterceptor.h @@ -67,6 +67,7 @@ class ChecksumInterceptor : public smithy::interceptor::Interceptor { } // Add RequestChecksum + addChecksumConfigruationFeautres(request); if ((!request.GetChecksumAlgorithmName().empty() && m_requestChecksumCalculation == RequestChecksumCalculation::WHEN_SUPPORTED) || request.RequestChecksumRequired()) { Aws::String checksumAlgorithmName = Aws::Utils::StringUtils::ToLower(request.GetChecksumAlgorithmName().c_str()); @@ -82,35 +83,41 @@ class ChecksumInterceptor : public smithy::interceptor::Interceptor { // For streaming payload, the resolved checksum location depends on whether it is an unsigned payload, we let // AwsAuthSigner decide it. if (request.IsStreaming() && checksumValueAndAlgorithmProvided) { + addChecksumFeatureForChecksumName(checksumAlgorithmName, request); const auto hash = Aws::MakeShared(AWS_SMITHY_CLIENT_CHECKSUM, checksumHeader->second); httpRequest->SetRequestHash(checksumAlgorithmName, hash); } else if (checksumValueAndAlgorithmProvided) { httpRequest->SetHeaderValue(checksumType, checksumHeader->second); } else if (checksumAlgorithmName == "crc64nvme") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC64); if (request.IsStreaming()) { httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared(AWS_SMITHY_CLIENT_CHECKSUM)); } else { httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateCRC64(*(GetBodyStream(request))))); } } else if (checksumAlgorithmName == "crc32") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32); if (request.IsStreaming()) { httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared(AWS_SMITHY_CLIENT_CHECKSUM)); } else { httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateCRC32(*(GetBodyStream(request))))); } } else if (checksumAlgorithmName == "crc32c") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C); if (request.IsStreaming()) { httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared(AWS_SMITHY_CLIENT_CHECKSUM)); } else { httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateCRC32C(*(GetBodyStream(request))))); } } else if (checksumAlgorithmName == "sha256") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA256); if (request.IsStreaming()) { httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared(AWS_SMITHY_CLIENT_CHECKSUM)); } else { httpRequest->SetHeaderValue(checksumType, HashingUtils::Base64Encode(HashingUtils::CalculateSHA256(*(GetBodyStream(request))))); } } else if (checksumAlgorithmName == "sha1") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA1); if (request.IsStreaming()) { httpRequest->SetRequestHash(checksumAlgorithmName, Aws::MakeShared(AWS_SMITHY_CLIENT_CHECKSUM)); } else { @@ -188,6 +195,36 @@ class ChecksumInterceptor : public smithy::interceptor::Interceptor { } private: + void addChecksumFeatureForChecksumName(const Aws::String& checksumName, const Aws::AmazonWebServiceRequest& request) { + if (checksumName == "crc32") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C); + } else if (checksumName == "crc32c") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C); + } else if (checksumName == "crc64") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC64); + } else if (checksumName == "sha1") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA1); + } else if (checksumName == "sha256") { + request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA256); + } else { + AWS_LOGSTREAM_ERROR(AWS_SMITHY_CLIENT_CHECKSUM, "could not add useragent feature for checksum " << checksumName); + } + } + + void addChecksumConfigruationFeautres(const Aws::AmazonWebServiceRequest& request) { + switch (m_requestChecksumCalculation) { + case RequestChecksumCalculation::WHEN_SUPPORTED: request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED); break; + case RequestChecksumCalculation::WHEN_REQUIRED: request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED);break; + default: AWS_LOG_ERROR(AWS_SMITHY_CLIENT_CHECKSUM, "could not add useragent feature for checksum request configuration"); break; + } + + switch (m_responseChecksumValidation) { + case ResponseChecksumValidation::WHEN_SUPPORTED: request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED); break; + case ResponseChecksumValidation::WHEN_REQUIRED: request.AddUserAgentFeature(Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED); break; + default: AWS_LOG_ERROR(AWS_SMITHY_CLIENT_CHECKSUM, "could not add useragent feature for checksum response configuration"); break; + } + } + RequestChecksumCalculation m_requestChecksumCalculation{RequestChecksumCalculation::WHEN_SUPPORTED}; ResponseChecksumValidation m_responseChecksumValidation{ResponseChecksumValidation::WHEN_SUPPORTED}; }; diff --git a/src/aws-cpp-sdk-core/source/client/UserAgent.cpp b/src/aws-cpp-sdk-core/source/client/UserAgent.cpp index e7b7f1e15c2..f0cc5adc08c 100644 --- a/src/aws-cpp-sdk-core/source/client/UserAgent.cpp +++ b/src/aws-cpp-sdk-core/source/client/UserAgent.cpp @@ -24,7 +24,16 @@ const std::pair BUSINESS_METRIC_MAPPING[] = { {UserAgentFeature::RETRY_MODE_ADAPTIVE, "F"}, {UserAgentFeature::S3_TRANSFER, "G"}, {UserAgentFeature::S3_CRYPTO_V1N, "H"}, - {UserAgentFeature::S3_CRYPTO_V2, "I"} + {UserAgentFeature::S3_CRYPTO_V2, "I"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32, "U"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C, "V"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC64, "W"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA1, "X"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA256, "Y"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED, "Z"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED, "a"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED, "b"}, + {UserAgentFeature::FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED, "c"} }; Aws::String BusinessMetricForFeature(UserAgentFeature feature) { diff --git a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp index d5f1ceaf261..c7692d6d864 100644 --- a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp +++ b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp @@ -331,7 +331,8 @@ TEST_F(S3UnitTest, PutObjectShouldHaveCorrectUserAgent) { EXPECT_TRUE(crtMetadata != userAgentParsed.end()); auto archMetadata = std::find_if(userAgentParsed.begin(), userAgentParsed.end(), [](const Aws::String & value) { return value.find("md/arch") != Aws::String::npos; }); EXPECT_TRUE(archMetadata != userAgentParsed.end()); - auto businessMetrics = std::find_if(userAgentParsed.begin(), userAgentParsed.end(), [](const Aws::String & value) { return value.find("m/") != Aws::String::npos; }); + // RETRY_MODE_STANDARD -> E, FLEXIBLE_CHECKSUMS_REQ_CRC64 -> W,FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED -> Z, FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED -> b + auto businessMetrics = std::find_if(userAgentParsed.begin(), userAgentParsed.end(), [](const Aws::String & value) { return value.find("m/E,W,Z,b") != Aws::String::npos; }); EXPECT_TRUE(businessMetrics != userAgentParsed.end()); // assert the order of the UA header