Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 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,7 @@ enum class UserAgentFeature {
S3_TRANSFER,
S3_CRYPTO_V1N,
S3_CRYPTO_V2,
S3_EXPRESS_BUCKET,
FLEXIBLE_CHECKSUMS_REQ_CRC32,
FLEXIBLE_CHECKSUMS_REQ_CRC32C,
FLEXIBLE_CHECKSUMS_REQ_CRC64,
Expand Down
5 changes: 5 additions & 0 deletions src/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/event/EventStream.h>
#include <aws/core/utils/UUID.h>
#include <aws/core/client/UserAgent.h>
#include <smithy/tracing/TracingUtils.h>

using namespace Aws;
Expand Down Expand Up @@ -53,6 +54,10 @@ XmlOutcome AWSXMLClient::MakeRequest(const Aws::AmazonWebServiceRequest& request
const char* signerServiceNameOverride /* = nullptr */) const
{
const Aws::Http::URI& uri = endpoint.GetURI();
// Add S3Express user agent feature if backend is S3Express
if (endpoint.GetAttributes() && endpoint.GetAttributes()->backend == "S3Express") {
request.AddUserAgentFeature(Aws::Client::UserAgentFeature::S3_EXPRESS_BUCKET);
}
if (endpoint.GetAttributes()) {
signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
Expand Down
1 change: 1 addition & 0 deletions src/aws-cpp-sdk-core/source/client/UserAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const std::pair<UserAgentFeature, const char*> BUSINESS_METRIC_MAPPING[] = {
{UserAgentFeature::S3_TRANSFER, "G"},
{UserAgentFeature::S3_CRYPTO_V1N, "H"},
{UserAgentFeature::S3_CRYPTO_V2, "I"},
{UserAgentFeature::S3_EXPRESS_BUCKET, "J"},
{UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32, "U"},
{UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C, "V"},
{UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC64, "W"},
Expand Down
31 changes: 31 additions & 0 deletions tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,37 @@ TEST_F(S3UnitTest, PutObjectShouldHaveCorrectUserAgent) {
EXPECT_TRUE(archMetadata < businessMetrics);
}

TEST_F(S3UnitTest, PutObjectS3ExpressShouldHaveJMetric) {
auto request = PutObjectRequest()
.WithBucket("o-worthy-heart--usw2-az1--x-s3") // S3Express bucket pattern
.WithKey("who-tempers-anxiety-into-strength");

std::shared_ptr<IOStream> body = Aws::MakeShared<StringStream>(ALLOCATION_TAG, "time marches on, and the age of a new king draws nearer");
request.SetBody(body);

auto mockRequest = Aws::MakeShared<Standard::StandardHttpRequest>(ALLOCATION_TAG, "alonzo.com/faker", HttpMethod::HTTP_PUT);
mockRequest->SetResponseStreamFactory([]() -> IOStream* {
return Aws::New<StringStream>(ALLOCATION_TAG, "", std::ios_base::in | std::ios_base::binary);
});
auto mockResponse = Aws::MakeShared<Standard::StandardHttpResponse>(ALLOCATION_TAG, mockRequest);
mockResponse->SetResponseCode(HttpResponseCode::OK);

_mockHttpClient->AddResponseToReturn(mockResponse);

const auto response = _s3Client->PutObject(request);

const auto requestSeen = _mockHttpClient->GetMostRecentHttpRequest();
EXPECT_TRUE(requestSeen.HasUserAgent());
const auto& userAgent = requestSeen.GetUserAgent();
EXPECT_TRUE(!userAgent.empty());
const auto userAgentParsed = Utils::StringUtils::Split(userAgent, ' ');

// Check for S3Express business metric (J) in user agent
auto businessMetrics = std::find_if(userAgentParsed.begin(), userAgentParsed.end(),
[](const Aws::String & value) { return value.find("m/") != Aws::String::npos && value.find("J") != Aws::String::npos; });
EXPECT_TRUE(businessMetrics != userAgentParsed.end());
}

TEST_F(S3UnitTest, RequestShouldNotIncludeAChecksumIfNotRequired) {
S3ClientConfiguration configuration{};
configuration.checksumConfig.requestChecksumCalculation = RequestChecksumCalculation::WHEN_REQUIRED;
Expand Down
Loading