diff --git a/.cspell.json b/.cspell.json index b72ea55deb2..6b2e04fec4d 100644 --- a/.cspell.json +++ b/.cspell.json @@ -64,6 +64,9 @@ "ALLOC", "ISOE", "isoe", + "authscheme", + "Vistor", + "eventstreaming", // AWS general "Arns", "AMZN", @@ -77,6 +80,9 @@ "AWSSTL", "reparsed", "reparses", + "MRAP", + "ISOF", + "isof", // AWS Signature "SIGV", "AUTHV", diff --git a/src/aws-cpp-sdk-core/include/smithy/client/features/ChunkingInterceptor.h b/src/aws-cpp-sdk-core/include/smithy/client/features/ChunkingInterceptor.h index 2ed637db883..0b377593fb8 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/features/ChunkingInterceptor.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/features/ChunkingInterceptor.h @@ -156,9 +156,41 @@ class ChunkingInterceptor : public smithy::interceptor::Interceptor { ~ChunkingInterceptor() override = default; ModifyRequestOutcome ModifyBeforeSigning(smithy::interceptor::InterceptorContext& context) override { + auto request = context.GetTransmitRequest(); + + if (!ShouldApplyChunking(request, context)) { + return request; + } + + const auto& hashPair = request->GetRequestHash(); + if (hashPair.second != nullptr) { + Aws::String checksumHeaderValue = Aws::String(CHECKSUM_HEADER_PREFIX) + hashPair.first; + request->DeleteHeader(checksumHeaderValue.c_str()); + request->SetHeaderValue(Aws::Http::AWS_TRAILER_HEADER, checksumHeaderValue); + request->SetTransferEncoding(Aws::Http::CHUNKED_VALUE); + + if (!request->HasContentEncoding()) { + request->SetContentEncoding(Aws::Http::AWS_CHUNKED_VALUE); + } else { + Aws::String currentEncoding = request->GetContentEncoding(); + if (currentEncoding.find(Aws::Http::AWS_CHUNKED_VALUE) == Aws::String::npos) { + request->SetContentEncoding(Aws::String{Aws::Http::AWS_CHUNKED_VALUE} + "," + currentEncoding); + } + } + + if (request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER)) { + request->SetHeaderValue(Aws::Http::DECODED_CONTENT_LENGTH_HEADER, request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER)); + request->DeleteHeader(Aws::Http::CONTENT_LENGTH_HEADER); + } + } + + return context.GetTransmitRequest(); + } + + ModifyRequestOutcome ModifyBeforeTransmit(smithy::interceptor::InterceptorContext& context) override { auto request = context.GetTransmitRequest(); - if (!ShouldApplyChunking(request)) { + if (!ShouldApplyChunking(request, context)) { return request; } @@ -167,29 +199,6 @@ class ChunkingInterceptor : public smithy::interceptor::Interceptor { return request; } - // Set up chunked encoding headers for checksum calculation - const auto& hashPair = request->GetRequestHash(); - if (hashPair.second != nullptr) { - Aws::String checksumHeaderValue = Aws::String(CHECKSUM_HEADER_PREFIX) + hashPair.first; - request->DeleteHeader(checksumHeaderValue.c_str()); - request->SetHeaderValue(Aws::Http::AWS_TRAILER_HEADER, checksumHeaderValue); - request->SetTransferEncoding(Aws::Http::CHUNKED_VALUE); - - if (!request->HasContentEncoding()) { - request->SetContentEncoding(Aws::Http::AWS_CHUNKED_VALUE); - } else { - Aws::String currentEncoding = request->GetContentEncoding(); - if (currentEncoding.find(Aws::Http::AWS_CHUNKED_VALUE) == Aws::String::npos) { - request->SetContentEncoding(Aws::String{Aws::Http::AWS_CHUNKED_VALUE} + "," + currentEncoding); - } - } - - if (request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER)) { - request->SetHeaderValue(Aws::Http::DECODED_CONTENT_LENGTH_HEADER, request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER)); - request->DeleteHeader(Aws::Http::CONTENT_LENGTH_HEADER); - } - } - auto chunkedBody = Aws::MakeShared( ALLOCATION_TAG, request.get(), originalBody); @@ -202,7 +211,13 @@ class ChunkingInterceptor : public smithy::interceptor::Interceptor { } private: - bool ShouldApplyChunking(const std::shared_ptr& request) const { + bool ShouldApplyChunking(const std::shared_ptr& request, + const smithy::interceptor::InterceptorContext& context) const { + //TODO: remove this once we figure out why MRAP cannot trail chunk + const auto signerName = context.GetAttribute("signer_name"); + if (signerName.has_value() && signerName.value() == "AsymmetricSignatureV4") { + return false; + } // Use configuration setting to determine chunking behavior if (m_httpClientChunkedMode != Aws::Client::HttpClientChunkedMode::DEFAULT) { return false; diff --git a/src/aws-cpp-sdk-core/include/smithy/interceptor/Interceptor.h b/src/aws-cpp-sdk-core/include/smithy/interceptor/Interceptor.h index b133857624b..e9de73150c1 100644 --- a/src/aws-cpp-sdk-core/include/smithy/interceptor/Interceptor.h +++ b/src/aws-cpp-sdk-core/include/smithy/interceptor/Interceptor.h @@ -16,6 +16,7 @@ namespace smithy using ModifyRequestOutcome = Aws::Utils::Outcome, Aws::Client::AWSError>; virtual ModifyRequestOutcome ModifyBeforeSigning(InterceptorContext& context) = 0; + virtual ModifyRequestOutcome ModifyBeforeTransmit(InterceptorContext& context) { return context.GetTransmitRequest(); } using ModifyResponseOutcome = Aws::Utils::Outcome, Aws::Client::AWSError>; virtual ModifyResponseOutcome ModifyBeforeDeserialization(InterceptorContext& context) = 0; diff --git a/src/aws-cpp-sdk-core/include/smithy/interceptor/InterceptorContext.h b/src/aws-cpp-sdk-core/include/smithy/interceptor/InterceptorContext.h index 08cfc836f37..03c96e89558 100644 --- a/src/aws-cpp-sdk-core/include/smithy/interceptor/InterceptorContext.h +++ b/src/aws-cpp-sdk-core/include/smithy/interceptor/InterceptorContext.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace smithy { @@ -53,9 +54,12 @@ namespace smithy m_transmitResponse = transmitResponse; } - Aws::String GetAttribute(const Aws::String& key) const - { - return m_attributes.at(key); + Aws::Crt::Optional GetAttribute(const Aws::String& key) const { + const auto attribute = m_attributes.find(key); + if (attribute == m_attributes.end()) { + return {}; + } + return attribute->second; } void SetAttribute(const Aws::String& key, const Aws::String& value) diff --git a/src/aws-cpp-sdk-core/source/client/AWSClient.cpp b/src/aws-cpp-sdk-core/source/client/AWSClient.cpp index 90f83a58f33..4dbc7895352 100644 --- a/src/aws-cpp-sdk-core/source/client/AWSClient.cpp +++ b/src/aws-cpp-sdk-core/source/client/AWSClient.cpp @@ -570,6 +570,7 @@ HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptrModifyBeforeSigning(context); @@ -597,6 +598,13 @@ HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptrModifyBeforeTransmit(context); + if (!modifiedRequest.IsSuccess()) { + return modifiedRequest.GetError(); + } + } + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request Successfully signed"); auto httpResponse = TracingUtils::MakeCallWithTiming>( [&]() -> std::shared_ptr { 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 34f33336d36..f185bfacc74 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp @@ -426,6 +426,19 @@ void AwsSmithyClientBase::AttemptOneRequestAsync(std::shared_ptrModifyBeforeTransmit(*pRequestCtx->m_interceptorContext); + if (!modifiedRequest.IsSuccess()) + { + pExecutor->Submit([modifiedRequest, responseHandler]() mutable + { + responseHandler(modifiedRequest.GetError()); + }); + return; + } + } + // TODO: async http client #if 0 AWS_LOGSTREAM_DEBUG(AWS_SMITHY_CLIENT_LOG, "Request Successfully signed");