Skip to content

Fix query compatible for JSON services #3468

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
54 changes: 13 additions & 41 deletions src/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse

if (httpResponse.HasHeader(ERROR_TYPE_HEADER)) {
error = Marshall(httpResponse.GetHeader(ERROR_TYPE_HEADER), message);
} else if (httpResponse.HasHeader(QUERY_ERROR_HEADER)) {
auto errorCodeString = httpResponse.GetHeader(QUERY_ERROR_HEADER);
auto locationOfSemicolon = errorCodeString.find_first_of(';');
Aws::String errorCode;

if (locationOfSemicolon != Aws::String::npos) {
errorCode = errorCodeString.substr(0, locationOfSemicolon);
} else {
errorCode = errorCodeString;
}
error = Marshall(errorCode, message);
} else if (payloadView.ValueExists(TYPE)) {
error = Marshall(payloadView.GetString(TYPE), message);
} else {
Expand Down Expand Up @@ -256,45 +267,6 @@ AWSError<CoreErrors> AWSErrorMarshaller::FindErrorByHttpResponseCode(Aws::Http::
}

void JsonErrorMarshallerQueryCompatible::MarshallError(AWSError<CoreErrors>& error, const Http::HttpResponse& httpResponse) const {
if (!error.GetExceptionName().empty()) {
auto exceptionPayload = GetJsonPayloadHttpResponse(httpResponse);
auto payloadView = JsonView(exceptionPayload);
/*
AWS Query-Compatible mode: This is a special setting that allows
certain AWS services to communicate using a specific "query"
format, which can send customized error codes. Users are divided
into different groups based on how they communicate with the
service: Group #1: Users using the AWS Query format, receiving
custom error codes. Group #2: Users using the regular AWS JSON
format without the trait, receiving standard error codes. Group #3:
Users using the AWS JSON format with the trait, receiving custom
error codes.

The header "x-amzn-query-error" shouldn't be present if it's not
awsQueryCompatible, so added checks for it.
*/

if (httpResponse.HasHeader(QUERY_ERROR_HEADER)) {
auto errorCodeString = httpResponse.GetHeader(QUERY_ERROR_HEADER);
auto locationOfSemicolon = errorCodeString.find_first_of(';');
Aws::String errorCode;

if (locationOfSemicolon != Aws::String::npos) {
errorCode = errorCodeString.substr(0, locationOfSemicolon);
} else {
errorCode = errorCodeString;
}

error.SetExceptionName(errorCode);
}
// check for exception name from payload field 'type'
else if (payloadView.ValueExists(TYPE)) {
// handle missing header and parse code from message
const auto& typeStr = payloadView.GetString(TYPE);
auto locationOfPound = typeStr.find_first_of('#');
if (locationOfPound != Aws::String::npos) {
error.SetExceptionName(typeStr.substr(locationOfPound + 1));
}
}
}
AWS_UNREFERENCED_PARAM(error);
AWS_UNREFERENCED_PARAM(httpResponse);
}
Original file line number Diff line number Diff line change
Expand Up @@ -477,9 +477,9 @@ TEST_F(AWSErrorMarshallerTest, TestErrorsWithPrefixParse)
JsonErrorMarshallerQueryCompatible awsErrorMarshaller2;
error = awsErrorMarshaller2.Marshall(
*BuildHttpResponse(exceptionPrefix + "AccessDeniedException", message, requestId, LowerCaseMessage, "AwsQueryErrorCode"));
ASSERT_EQ(CoreErrors::ACCESS_DENIED, error.GetErrorType());
ASSERT_EQ(CoreErrors::UNKNOWN, error.GetErrorType());
ASSERT_EQ("AwsQueryErrorCode", error.GetExceptionName());
ASSERT_EQ(message, error.GetMessage());
ASSERT_EQ("Unable to parse ExceptionName: AwsQueryErrorCode Message: Test Message", error.GetMessage());
ASSERT_EQ(requestId, error.GetRequestId());
ASSERT_FALSE(error.ShouldRetry());
}
Expand Down Expand Up @@ -746,9 +746,9 @@ TEST_F(AWSErrorMarshallerTest, TestErrorsWithoutPrefixParse)
JsonErrorMarshallerQueryCompatible awsErrorMarshaller2;
error = awsErrorMarshaller2.Marshall(
*BuildHttpResponse(exceptionPrefix + "AccessDeniedException", message, requestId, LowerCaseMessage, "AwsQueryErrorCode"));
ASSERT_EQ(CoreErrors::ACCESS_DENIED, error.GetErrorType());
ASSERT_EQ(CoreErrors::UNKNOWN, error.GetErrorType());
ASSERT_EQ("AwsQueryErrorCode", error.GetExceptionName());
ASSERT_EQ(message, error.GetMessage());
ASSERT_EQ("Unable to parse ExceptionName: AwsQueryErrorCode Message: Test Message", error.GetMessage());
ASSERT_EQ(requestId, error.GetRequestId());
ASSERT_FALSE(error.ShouldRetry());
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <aws/core/utils/memory/AWSMemory.h>
#include <aws/monitoring/CloudWatchClient.h>
#include <aws/monitoring/model/PutMetricDataRequest.h>
#include <aws/monitoring/model/GetDashboardRequest.h>
#include <aws/testing/AwsTestHelpers.h>
#include <aws/testing/TestingEnvironment.h>
#include <gtest/gtest.h>
Expand Down Expand Up @@ -91,4 +92,12 @@ TEST_F(CloudWatchMonitoringOperationTest, PutLargeMetricDataTest) {
m_client->PutMetricData(request);
AWS_ASSERT_SUCCESS(outcome);
}

TEST_F(CloudWatchMonitoringOperationTest, DashboardNotFoundShouldParseCorrectly) {
const auto response = m_client->GetDashboard(GetDashboardRequest().WithDashboardName("foo"));
EXPECT_FALSE(response.IsSuccess());
EXPECT_EQ(CloudWatchErrors::DASHBOARD_NOT_FOUND, response.GetError().GetErrorType());
EXPECT_EQ("ResourceNotFound", response.GetError().GetExceptionName());
EXPECT_EQ("Dashboard foo does not exist", response.GetError().GetMessage());
}
} // namespace
Loading