From c02e9397e1289c8aee55130a89cffc93ab7c871b Mon Sep 17 00:00:00 2001 From: sbaluja Date: Thu, 2 Jul 2026 13:01:57 -0400 Subject: [PATCH 1/3] 100-continue round trip fix (only for streaming now) --- .../include/aws/core/client/AWSClient.h | 1 + .../aws/core/client/ClientConfiguration.h | 17 ++- .../include/aws/core/http/HttpRequest.h | 2 + .../aws/core/http/curl/CurlHttpClient.h | 1 - .../source/client/AWSClient.cpp | 13 +- .../source/http/HttpRequest.cpp | 2 + .../source/http/curl/CurlHttpClient.cpp | 4 +- .../smithy/client/AwsSmithyClientBase.cpp | 5 + .../DynamoDBUnitTests.cpp | 27 +++- .../aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp | 129 ++++++++++++++++++ 10 files changed, 186 insertions(+), 15 deletions(-) diff --git a/src/aws-cpp-sdk-core/include/aws/core/client/AWSClient.h b/src/aws-cpp-sdk-core/include/aws/core/client/AWSClient.h index 9b0d9a6bbca8..1815b88abd9f 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/client/AWSClient.h +++ b/src/aws-cpp-sdk-core/include/aws/core/client/AWSClient.h @@ -364,6 +364,7 @@ namespace Aws std::shared_ptr m_userAgentInterceptor; Aws::Vector> m_interceptors; bool m_enableNewRetries; + bool m_disableExpectHeader; }; AWS_CORE_API Aws::String GetAuthorizationHeader(const Aws::Http::HttpRequest& httpRequest); diff --git a/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h b/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h index a5c164384a7b..9799edfa69ab 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h +++ b/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h @@ -352,13 +352,16 @@ namespace Aws FollowRedirectsPolicy followRedirects; /** - * Only works for Curl http client. - * Curl will by default add "Expect: 100-Continue" header in a Http request so as to avoid sending http - * payload to wire if server respond error immediately after receiving the header. - * Set this option to true will tell Curl to send http request header and body together. - * This can save one round-trip time and especially useful when the payload is small and network latency is more important. - * But be careful when Http request has large payload such S3 PutObject. You don't want to spend long time sending a large payload just getting a error response for server. - * The default value will be false. + * When set to true, the SDK will NOT add "Expect: 100-Continue" header to any HTTP request, + * including streaming operations like S3 PutObject or UploadPart. + * + * By default (false), the SDK automatically adds "Expect: 100-Continue" only to streaming + * requests (operations with streaming input bodies). This allows the server to reject the + * request before the client sends a potentially large payload, saving bandwidth on failures. + * Non-streaming requests never receive the Expect header regardless of this setting. + * + * Set to true if you are going through a proxy or middleware that does not correctly + * handle the Expect: 100-Continue mechanism. */ bool disableExpectHeader = false; diff --git a/src/aws-cpp-sdk-core/include/aws/core/http/HttpRequest.h b/src/aws-cpp-sdk-core/include/aws/core/http/HttpRequest.h index b7c431a30f3b..cb21d943d253 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/http/HttpRequest.h +++ b/src/aws-cpp-sdk-core/include/aws/core/http/HttpRequest.h @@ -63,6 +63,8 @@ namespace Aws extern AWS_CORE_API const char X_AMZN_TRACE_ID_HEADER[]; extern AWS_CORE_API const char CHUNKED_VALUE[]; extern AWS_CORE_API const char AWS_CHUNKED_VALUE[]; + extern AWS_CORE_API const char EXPECT_HEADER[]; + extern AWS_CORE_API const char EXPECT_100_CONTINUE_VALUE[]; extern AWS_CORE_API const char X_AMZN_ERROR_TYPE[]; extern AWS_CORE_API const char X_AMZN_QUERY_MODE[]; diff --git a/src/aws-cpp-sdk-core/include/aws/core/http/curl/CurlHttpClient.h b/src/aws-cpp-sdk-core/include/aws/core/http/curl/CurlHttpClient.h index 5dca8be738ff..0a5f45f2d83b 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/http/curl/CurlHttpClient.h +++ b/src/aws-cpp-sdk-core/include/aws/core/http/curl/CurlHttpClient.h @@ -70,7 +70,6 @@ class AWS_CORE_API CurlHttpClient: public HttpClient Aws::String m_caFile; Aws::String m_proxyCaPath; Aws::String m_proxyCaFile; - bool m_disableExpectHeader = false; bool m_allowRedirects = false; bool m_enableHttpClientTrace = false; Aws::Http::TransferLibPerformanceMode m_perfMode = TransferLibPerformanceMode::LOW_LATENCY; diff --git a/src/aws-cpp-sdk-core/source/client/AWSClient.cpp b/src/aws-cpp-sdk-core/source/client/AWSClient.cpp index 0b0c63a7f0df..c0253901d1ed 100644 --- a/src/aws-cpp-sdk-core/source/client/AWSClient.cpp +++ b/src/aws-cpp-sdk-core/source/client/AWSClient.cpp @@ -144,7 +144,8 @@ AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, m_httpClient->IsDefaultAwsHttpClient() ? Aws::Client::HttpClientChunkedMode::DEFAULT : configuration.httpClientChunkedMode, configuration.awsChunkedBufferSize), m_userAgentInterceptor}, - m_enableNewRetries{Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026").c_str()) == "true"} + m_enableNewRetries{Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026").c_str()) == "true"}, + m_disableExpectHeader(configuration.disableExpectHeader) { } @@ -170,11 +171,12 @@ AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment), m_requestCompressionConfig(configuration.requestCompressionConfig), m_userAgentInterceptor{Aws::MakeShared(AWS_CLIENT_LOG_TAG, configuration, m_retryStrategy->GetStrategyName(), m_serviceName)}, - m_interceptors{Aws::MakeShared(AWS_CLIENT_LOG_TAG, configuration), Aws::MakeShared(AWS_CLIENT_LOG_TAG, + m_interceptors{Aws::MakeShared(AWS_CLIENT_LOG_TAG, configuration), Aws::MakeShared(AWS_CLIENT_LOG_TAG, m_httpClient->IsDefaultAwsHttpClient() ? Aws::Client::HttpClientChunkedMode::DEFAULT : configuration.httpClientChunkedMode, configuration.awsChunkedBufferSize), m_userAgentInterceptor}, - m_enableNewRetries{Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026").c_str()) == "true"} + m_enableNewRetries{Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026").c_str()) == "true"}, + m_disableExpectHeader(configuration.disableExpectHeader) { } @@ -953,6 +955,11 @@ void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, co request.AddUserAgentFeature(Aws::Client::UserAgentFeature::PROTOCOL_RPC_V2_CBOR); } + if (request.IsStreaming() && !m_disableExpectHeader) + { + httpRequest->SetHeaderValue(Aws::Http::EXPECT_HEADER, Aws::Http::EXPECT_100_CONTINUE_VALUE); + } + // Pass along handlers for processing data sent/received in bytes httpRequest->SetHeadersReceivedEventHandler(request.GetHeadersReceivedEventHandler()); httpRequest->SetDataReceivedEventHandler(request.GetDataReceivedEventHandler()); diff --git a/src/aws-cpp-sdk-core/source/http/HttpRequest.cpp b/src/aws-cpp-sdk-core/source/http/HttpRequest.cpp index b4bfd5435c6d..55ca99c64661 100644 --- a/src/aws-cpp-sdk-core/source/http/HttpRequest.cpp +++ b/src/aws-cpp-sdk-core/source/http/HttpRequest.cpp @@ -42,6 +42,8 @@ namespace Aws const char AWS_CHUNKED_VALUE[] = "aws-chunked"; const char X_AMZN_TRACE_ID_HEADER[] = "X-Amzn-Trace-Id"; const char ALLOCATION_TAG[] = "HttpRequestConversion"; + const char EXPECT_HEADER[] = "expect"; + const char EXPECT_100_CONTINUE_VALUE[] = "100-continue"; const char X_AMZN_ERROR_TYPE[] = "x-amzn-errortype"; const char X_AMZN_QUERY_MODE[] = "x-amzn-query-mode"; std::shared_ptr HttpRequest::ToCrtHttpRequest() diff --git a/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp b/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp index 6a16d7c9b2e6..119fd788b74a 100644 --- a/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp +++ b/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp @@ -610,7 +610,6 @@ CurlHttpClient::CurlHttpClient(const ClientConfiguration& clientConfig) : m_proxyKeyPasswd(clientConfig.proxySSLKeyPassword), m_proxyPort(clientConfig.proxyPort), m_verifySSL(clientConfig.verifySSL), m_revokeBestEffort(clientConfig.curlOptions.revokeBestEffort), m_caPath(clientConfig.caPath), m_caFile(clientConfig.caFile), m_proxyCaPath(clientConfig.proxyCaPath), m_proxyCaFile(clientConfig.proxyCaFile), - m_disableExpectHeader(clientConfig.disableExpectHeader), m_enableHttpClientTrace(clientConfig.enableHttpClientTrace || FORCE_ENABLE_CURL_LOGGING), m_perfMode(clientConfig.httpLibPerfMode), m_telemetryProvider(clientConfig.telemetryProvider) @@ -685,8 +684,7 @@ std::shared_ptr CurlHttpClient::MakeRequest(const std::shared_ptr< headers = curl_slist_append(headers, "content-type:"); } - // Discard Expect header so as to avoid using multiple payloads to send a http request (header + body) - if (m_disableExpectHeader) + if (!request->HasHeader(Http::EXPECT_HEADER)) { headers = curl_slist_append(headers, "Expect:"); } diff --git a/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp b/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp index b7da57e16b0a..d925a2efd68d 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp @@ -174,6 +174,11 @@ AwsSmithyClientBase::BuildHttpRequest(const std::shared_ptrIsStreaming() && !m_clientConfig->disableExpectHeader) + { + httpRequest->SetHeaderValue(Aws::Http::EXPECT_HEADER, Aws::Http::EXPECT_100_CONTINUE_VALUE); + } + // Pass along handlers for processing data sent/received in bytes httpRequest->SetHeadersReceivedEventHandler(pRequest->GetHeadersReceivedEventHandler()); httpRequest->SetDataReceivedEventHandler(pRequest->GetDataReceivedEventHandler()); diff --git a/tests/aws-cpp-sdk-dynamodb-unit-tests/DynamoDBUnitTests.cpp b/tests/aws-cpp-sdk-dynamodb-unit-tests/DynamoDBUnitTests.cpp index 4ac91e53012e..e2f376302b2e 100644 --- a/tests/aws-cpp-sdk-dynamodb-unit-tests/DynamoDBUnitTests.cpp +++ b/tests/aws-cpp-sdk-dynamodb-unit-tests/DynamoDBUnitTests.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -807,4 +808,28 @@ TEST_F(DynamoDBUnitTest, ShouldWorkWhenAccountIDPresentAndRequired) EXPECT_TRUE(std::find(features.begin(), features.end(), "R") != features.end()); // Identity resolved a accountId EXPECT_TRUE(std::find(features.begin(), features.end(), "T") != features.end()); -} \ No newline at end of file +} + +TEST_F(DynamoDBUnitTest, PutItemDoesNotSendExpect100ContinueHeader) { + using namespace Aws::DynamoDB::Model; + + auto putItemRequest = PutItemRequest(); + putItemRequest.SetTableName("TestTable"); + AttributeValue hashKey; + hashKey.SetS("testKey"); + putItemRequest.AddItem("id", hashKey); + + auto mockStream = Aws::MakeShared(LOG_TAG, "mockuri", HttpMethod::HTTP_GET); + mockStream->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(LOG_TAG, "{}", std::ios_base::in | std::ios_base::binary); + }); + auto successResponse = Aws::MakeShared(LOG_TAG, mockStream); + successResponse->SetResponseCode(HttpResponseCode::OK); + mock_http_client_->AddResponseToReturn(successResponse); + + const auto putItemOutcome = client_->PutItem(putItemRequest); + EXPECT_TRUE(putItemOutcome.IsSuccess()); + + const auto requestSeen = mock_http_client_->GetMostRecentHttpRequest(); + EXPECT_FALSE(requestSeen.HasHeader("expect")); +} diff --git a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp index a40be6bdfc46..8e86de4b5d26 100644 --- a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp +++ b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -726,3 +727,131 @@ TEST_F(S3UnitTest, TestGetObjectTimeoutShouldReturnTimeoutError) { EXPECT_EQ(error.GetResponseCode(), HttpResponseCode::NETWORK_CONNECT_TIMEOUT); EXPECT_TRUE(error.ShouldRetry()); } + +TEST_F(S3UnitTest, PutObjectSendsExpect100ContinueHeader) { + auto putObjectRequest = PutObjectRequest() + .WithBucket("test-bucket") + .WithKey("test-key"); + + std::shared_ptr body = Aws::MakeShared(ALLOCATION_TAG, + "test body content", + std::ios_base::in | std::ios_base::binary); + putObjectRequest.SetBody(body); + + auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(ALLOCATION_TAG, "response", std::ios_base::in | std::ios_base::binary); + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->SetResponseCode(HttpResponseCode::OK); + _mockHttpClient->AddResponseToReturn(mockResponse); + + const auto response = _s3Client->PutObject(putObjectRequest); + AWS_EXPECT_SUCCESS(response); + + const auto seenRequest = _mockHttpClient->GetMostRecentHttpRequest(); + EXPECT_TRUE(seenRequest.HasHeader("expect")); + EXPECT_EQ("100-continue", seenRequest.GetHeaderValue("expect")); +} + +TEST_F(S3UnitTest, UploadPartSendsExpect100ContinueHeader) { + auto uploadPartRequest = UploadPartRequest() + .WithBucket("test-bucket") + .WithKey("test-key") + .WithUploadId("test-upload-id") + .WithPartNumber(1); + + std::shared_ptr body = Aws::MakeShared(ALLOCATION_TAG, + "test body content", + std::ios_base::in | std::ios_base::binary); + uploadPartRequest.SetBody(body); + + auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(ALLOCATION_TAG, "response", std::ios_base::in | std::ios_base::binary); + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->SetResponseCode(HttpResponseCode::OK); + _mockHttpClient->AddResponseToReturn(mockResponse); + + const auto response = _s3Client->UploadPart(uploadPartRequest); + AWS_EXPECT_SUCCESS(response); + + const auto seenRequest = _mockHttpClient->GetMostRecentHttpRequest(); + EXPECT_TRUE(seenRequest.HasHeader("expect")); + EXPECT_EQ("100-continue", seenRequest.GetHeaderValue("expect")); +} + +TEST_F(S3UnitTest, GetObjectDoesNotSendExpect100ContinueHeader) { + auto getObjectRequest = GetObjectRequest() + .WithBucket("test-bucket") + .WithKey("test-key"); + + auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(ALLOCATION_TAG, "response body", std::ios_base::in | std::ios_base::binary); + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->SetResponseCode(HttpResponseCode::OK); + _mockHttpClient->AddResponseToReturn(mockResponse); + + const auto response = _s3Client->GetObject(getObjectRequest); + AWS_EXPECT_SUCCESS(response); + + const auto seenRequest = _mockHttpClient->GetMostRecentHttpRequest(); + EXPECT_FALSE(seenRequest.HasHeader("expect")); +} + +TEST_F(S3UnitTest, ListObjectsV2DoesNotSendExpect100ContinueHeader) { + auto listRequest = ListObjectsV2Request() + .WithBucket("test-bucket"); + + auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(ALLOCATION_TAG, + "test-bucketfalse", + std::ios_base::in | std::ios_base::binary); + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->SetResponseCode(HttpResponseCode::OK); + _mockHttpClient->AddResponseToReturn(mockResponse); + + const auto response = _s3Client->ListObjectsV2(listRequest); + AWS_EXPECT_SUCCESS(response); + + const auto seenRequest = _mockHttpClient->GetMostRecentHttpRequest(); + EXPECT_FALSE(seenRequest.HasHeader("expect")); +} + +TEST_F(S3UnitTest, PutObjectWithDisableExpectHeaderDoesNotSendExpect) { + AWSCredentials credentials{"mock", "credentials"}; + const auto epProvider = Aws::MakeShared(ALLOCATION_TAG); + S3ClientConfiguration s3Config; + s3Config.region = "us-east-1"; + s3Config.retryStrategy = Aws::MakeShared(ALLOCATION_TAG); + s3Config.disableExpectHeader = true; + auto client = Aws::MakeShared(ALLOCATION_TAG, credentials, epProvider, s3Config); + + auto putObjectRequest = PutObjectRequest() + .WithBucket("test-bucket") + .WithKey("test-key"); + + std::shared_ptr body = Aws::MakeShared(ALLOCATION_TAG, + "test body content", + std::ios_base::in | std::ios_base::binary); + putObjectRequest.SetBody(body); + + auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(ALLOCATION_TAG, "response", std::ios_base::in | std::ios_base::binary); + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->SetResponseCode(HttpResponseCode::OK); + _mockHttpClient->AddResponseToReturn(mockResponse); + + const auto response = client->PutObject(putObjectRequest); + AWS_EXPECT_SUCCESS(response); + + const auto seenRequest = _mockHttpClient->GetMostRecentHttpRequest(); + EXPECT_FALSE(seenRequest.HasHeader("expect")); +} From c62cae5086aea416144cc98916b444fb449fdb0a Mon Sep 17 00:00:00 2001 From: sbaluja Date: Thu, 2 Jul 2026 13:42:43 -0400 Subject: [PATCH 2/3] Add cross-region write test (PutObject) --- .../BucketAndObjectOperationTest.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp index bf0953f6551a..bfb44f7a9d1f 100644 --- a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp @@ -2032,6 +2032,33 @@ namespace listObjectsOutcome = globalClient->ListObjects(listObjectsRequest); AWS_ASSERT_SUCCESS(listObjectsOutcome); + // Cross-region PutObject (streaming request with Expect: 100-continue). + // Verifies that 301 redirect + Expect interaction works correctly. + PutObjectRequest putObjectRequest; + putObjectRequest.SetBucket(fullBucketName); + putObjectRequest.SetKey("cross-region-test-key"); + auto body = Aws::MakeShared(ALLOCATION_TAG, "cross-region body"); + putObjectRequest.SetBody(body); + PutObjectOutcome putObjectOutcome = globalClient->PutObject(putObjectRequest); + AWS_ASSERT_SUCCESS(putObjectOutcome); + + // Verify the object was written correctly. + GetObjectRequest getObjectRequest; + getObjectRequest.SetBucket(fullBucketName); + getObjectRequest.SetKey("cross-region-test-key"); + GetObjectOutcome getObjectOutcome = globalClient->GetObject(getObjectRequest); + AWS_ASSERT_SUCCESS(getObjectOutcome); + Aws::StringStream getObjectBody; + getObjectBody << getObjectOutcome.GetResult().GetBody().rdbuf(); + EXPECT_EQ("cross-region body", getObjectBody.str()); + + // Clean up the object before deleting the bucket. + DeleteObjectRequest deleteObjectRequest; + deleteObjectRequest.SetBucket(fullBucketName); + deleteObjectRequest.SetKey("cross-region-test-key"); + DeleteObjectOutcome deleteObjectOutcome = globalClient->DeleteObject(deleteObjectRequest); + AWS_ASSERT_SUCCESS(deleteObjectOutcome); + DeleteBucketRequest deleteBucketRequest; deleteBucketRequest.SetBucket(fullBucketName); DeleteBucketOutcome deleteBucketOutcome = globalClient->DeleteBucket(deleteBucketRequest); From 9a9184df4f4db016434a76a909bc1c37f3b21351 Mon Sep 17 00:00:00 2001 From: sbaluja Date: Mon, 6 Jul 2026 14:21:03 -0400 Subject: [PATCH 3/3] Sigv4 signer don't sign the expect header --- src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp b/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp index bcca2d2e602f..7ebf65689524 100644 --- a/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp +++ b/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp @@ -64,7 +64,7 @@ AWSAuthV4Signer::AWSAuthV4Signer(const std::shared_ptr