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
6 changes: 6 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
"ALLOC",
"ISOE",
"isoe",
"authscheme",
"Vistor",
"eventstreaming",
// AWS general
"Arns",
"AMZN",
Expand All @@ -77,6 +80,9 @@
"AWSSTL",
"reparsed",
"reparses",
"MRAP",
"ISOF",
"isof",
// AWS Signature
"SIGV",
"AUTHV",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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<AwsChunkedIOStream>(
ALLOCATION_TAG, request.get(), originalBody);

Expand All @@ -202,7 +211,13 @@ class ChunkingInterceptor : public smithy::interceptor::Interceptor {
}

private:
bool ShouldApplyChunking(const std::shared_ptr<Aws::Http::HttpRequest>& request) const {
bool ShouldApplyChunking(const std::shared_ptr<Aws::Http::HttpRequest>& 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace smithy

using ModifyRequestOutcome = Aws::Utils::Outcome<std::shared_ptr<Aws::Http::HttpRequest>, Aws::Client::AWSError<Aws::Client::CoreErrors>>;
virtual ModifyRequestOutcome ModifyBeforeSigning(InterceptorContext& context) = 0;
virtual ModifyRequestOutcome ModifyBeforeTransmit(InterceptorContext& context) { return context.GetTransmitRequest(); }

using ModifyResponseOutcome = Aws::Utils::Outcome<std::shared_ptr<Aws::Http::HttpResponse>, Aws::Client::AWSError<Aws::Client::CoreErrors>>;
virtual ModifyResponseOutcome ModifyBeforeDeserialization(InterceptorContext& context) = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <aws/core/http/HttpRequest.h>
#include <aws/core/http/HttpResponse.h>
#include <aws/core/client/CoreErrors.h>
#include <aws/crt/Optional.h>

namespace smithy
{
Expand Down Expand Up @@ -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<Aws::String> 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)
Expand Down
8 changes: 8 additions & 0 deletions src/aws-cpp-sdk-core/source/client/AWSClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@ HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<Aws::Http

InterceptorContext context{request};
context.SetTransmitRequest(httpRequest);
context.SetAttribute("signer_name", signerName);
for (const auto& interceptor : m_interceptors)
{
const auto modifiedRequest = interceptor->ModifyBeforeSigning(context);
Expand Down Expand Up @@ -597,6 +598,13 @@ HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<Aws::Http
request.GetRequestSignedHandler()(*httpRequest);
}

for (const auto& interceptor : m_interceptors) {
const auto modifiedRequest = interceptor->ModifyBeforeTransmit(context);
if (!modifiedRequest.IsSuccess()) {
return modifiedRequest.GetError();
}
}

AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request Successfully signed");
auto httpResponse = TracingUtils::MakeCallWithTiming<std::shared_ptr<HttpResponse>>(
[&]() -> std::shared_ptr<HttpResponse> {
Expand Down
13 changes: 13 additions & 0 deletions src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,19 @@ void AwsSmithyClientBase::AttemptOneRequestAsync(std::shared_ptr<AwsSmithyClient
HandleAsyncReply(std::move(pRequestCtx), std::move(pResponse));
};

for (const auto& interceptor : m_interceptors)
{
auto modifiedRequest = interceptor->ModifyBeforeTransmit(*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");
Expand Down
Loading