Skip to content

Commit

Permalink
add flexible checksum business metrics to user agent
Browse files Browse the repository at this point in the history
  • Loading branch information
sbiscigl committed Jan 30, 2025
1 parent 6070213 commit c4b3898
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -241,7 +241,7 @@ namespace Aws
RequestSignedHandler m_onRequestSigned;
RequestRetryHandler m_requestRetryHandler;
mutable std::shared_ptr<Aws::Http::ServiceSpecificParameters> m_serviceSpecificParameters;
Aws::Set<Client::UserAgentFeature> m_userAgentFeatures;
mutable Aws::Set<Client::UserAgentFeature> m_userAgentFeatures;
};

} // namespace Aws
Expand Down
9 changes: 9 additions & 0 deletions src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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<PrecalculatedHash>(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<CRC64>(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<CRC32>(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<CRC32C>(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<Sha256>(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<Sha1>(AWS_SMITHY_CLIENT_CHECKSUM));
} else {
Expand Down Expand Up @@ -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};
};
Expand Down
11 changes: 10 additions & 1 deletion src/aws-cpp-sdk-core/source/client/UserAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,16 @@ const std::pair<UserAgentFeature, const char*> 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) {
Expand Down
3 changes: 2 additions & 1 deletion tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit c4b3898

Please sign in to comment.