123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- /**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
- #include <aws/core/client/AWSJsonClient.h>
- #include <aws/core/AmazonWebServiceRequest.h>
- #include <aws/core/auth/AWSAuthSignerProvider.h>
- #include <aws/core/client/AWSError.h>
- #include <aws/core/client/AWSErrorMarshaller.h>
- #include <aws/core/client/ClientConfiguration.h>
- #include <aws/core/client/CoreErrors.h>
- #include <aws/core/client/RetryStrategy.h>
- #include <aws/core/http/HttpClient.h>
- #include <aws/core/http/HttpResponse.h>
- #include <aws/core/http/URI.h>
- #include <aws/core/utils/json/JsonSerializer.h>
- #include <aws/core/utils/Outcome.h>
- #include <aws/core/utils/xml/XmlSerializer.h>
- #include <aws/core/utils/memory/stl/AWSStringStream.h>
- #include <aws/core/utils/logging/LogMacros.h>
- #include <aws/core/utils/event/EventStream.h>
- #include <aws/core/utils/UUID.h>
- #include <aws/core/monitoring/MonitoringManager.h>
- #include <cassert>
- using namespace Aws;
- using namespace Aws::Client;
- using namespace Aws::Http;
- using namespace Aws::Utils;
- using namespace Aws::Utils::Json;
- static const char AWS_JSON_CLIENT_LOG_TAG[] = "AWSJsonClient";
- AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
- const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer,
- const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
- BASECLASS(configuration, signer, errorMarshaller)
- {
- }
- AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
- const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider,
- const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
- BASECLASS(configuration, signerProvider, errorMarshaller)
- {
- }
- JsonOutcome AWSJsonClient::MakeRequest(const Aws::AmazonWebServiceRequest& request,
- const Aws::Endpoint::AWSEndpoint& endpoint,
- Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
- const char* signerName /* = Aws::Auth::NULL_SIGNER */,
- const char* signerRegionOverride /* = nullptr */,
- const char* signerServiceNameOverride /* = nullptr */) const
- {
- const Aws::Http::URI& uri = endpoint.GetURI();
- if (endpoint.GetAttributes()) {
- signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
- if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
- signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
- }
- if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
- signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
- }
- if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
- signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
- }
- }
- return MakeRequest(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride);
- }
- JsonOutcome AWSJsonClient::MakeRequest(const Aws::Endpoint::AWSEndpoint& endpoint,
- Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
- const char* signerName /* = Aws::Auth::NULL_SIGNER */,
- const char* signerRegionOverride /* = nullptr */,
- const char* signerServiceNameOverride /* = nullptr */) const
- {
- const Aws::Http::URI& uri = endpoint.GetURI();
- if (endpoint.GetAttributes()) {
- signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
- if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
- signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
- }
- if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
- signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
- }
- if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
- signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
- }
- }
- return MakeRequest(uri, method, signerName, signerRegionOverride, signerServiceNameOverride);
- }
- JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
- const Aws::AmazonWebServiceRequest& request,
- Http::HttpMethod method,
- const char* signerName,
- const char* signerRegionOverride,
- const char* signerServiceNameOverride) const
- {
- HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride));
- if (!httpOutcome.IsSuccess())
- {
- return JsonOutcome(std::move(httpOutcome));
- }
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
- //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()),
- httpOutcome.GetResult()->GetHeaders(),
- httpOutcome.GetResult()->GetResponseCode()));
- else
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
- }
- JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
- Http::HttpMethod method,
- const char* signerName,
- const char* requestName,
- const char* signerRegionOverride,
- const char* signerServiceNameOverride) const
- {
- HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride));
- if (!httpOutcome.IsSuccess())
- {
- return JsonOutcome(std::move(httpOutcome));
- }
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
- {
- JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
- if (!jsonValue.WasParseSuccessful())
- {
- return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
- }
- //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
- httpOutcome.GetResult()->GetHeaders(),
- httpOutcome.GetResult()->GetResponseCode()));
- }
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
- }
- JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const
- {
- // request is assumed to be signed
- std::shared_ptr<HttpResponse> httpResponse = MakeHttpRequest(request);
- if (DoesResponseGenerateError(httpResponse))
- {
- AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response");
- auto error = BuildAWSError(httpResponse);
- return JsonOutcome(std::move(error));
- }
- AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned successful response.");
- HttpResponseOutcome httpOutcome(std::move(httpResponse));
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
- {
- JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
- if (!jsonValue.WasParseSuccessful())
- {
- return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
- }
- //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
- httpOutcome.GetResult()->GetHeaders(),
- httpOutcome.GetResult()->GetResponseCode()));
- }
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
- }
- AWSError<CoreErrors> AWSJsonClient::BuildAWSError(
- const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const
- {
- AWSError<CoreErrors> error;
- if (httpResponse->HasClientError())
- {
- bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false;
- error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable);
- }
- else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1)
- {
- auto responseCode = httpResponse->GetResponseCode();
- auto errorCode = AWSClient::GuessBodylessErrorType(responseCode);
- Aws::StringStream ss;
- ss << "No response body.";
- error = AWSError<CoreErrors>(errorCode, "", ss.str(),
- IsRetryableHttpResponseCode(responseCode));
- }
- else
- {
- assert(httpResponse->GetResponseCode() != HttpResponseCode::OK);
- error = GetErrorMarshaller()->Marshall(*httpResponse);
- }
- error.SetResponseHeaders(httpResponse->GetHeaders());
- error.SetResponseCode(httpResponse->GetResponseCode());
- error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost());
- AWS_LOGSTREAM_ERROR(AWS_JSON_CLIENT_LOG_TAG, error);
- return error;
- }
|