AWSJsonClient.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/core/client/AWSJsonClient.h>
  6. #include <aws/core/AmazonWebServiceRequest.h>
  7. #include <aws/core/auth/AWSAuthSignerProvider.h>
  8. #include <aws/core/client/AWSError.h>
  9. #include <aws/core/client/AWSErrorMarshaller.h>
  10. #include <aws/core/client/ClientConfiguration.h>
  11. #include <aws/core/client/CoreErrors.h>
  12. #include <aws/core/client/RetryStrategy.h>
  13. #include <aws/core/http/HttpClient.h>
  14. #include <aws/core/http/HttpResponse.h>
  15. #include <aws/core/http/URI.h>
  16. #include <aws/core/utils/json/JsonSerializer.h>
  17. #include <aws/core/utils/Outcome.h>
  18. #include <aws/core/utils/xml/XmlSerializer.h>
  19. #include <aws/core/utils/memory/stl/AWSStringStream.h>
  20. #include <aws/core/utils/logging/LogMacros.h>
  21. #include <aws/core/utils/event/EventStream.h>
  22. #include <aws/core/utils/UUID.h>
  23. #include <aws/core/monitoring/MonitoringManager.h>
  24. #include <cassert>
  25. using namespace Aws;
  26. using namespace Aws::Client;
  27. using namespace Aws::Http;
  28. using namespace Aws::Utils;
  29. using namespace Aws::Utils::Json;
  30. static const char AWS_JSON_CLIENT_LOG_TAG[] = "AWSJsonClient";
  31. AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
  32. const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer,
  33. const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
  34. BASECLASS(configuration, signer, errorMarshaller)
  35. {
  36. }
  37. AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
  38. const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider,
  39. const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
  40. BASECLASS(configuration, signerProvider, errorMarshaller)
  41. {
  42. }
  43. JsonOutcome AWSJsonClient::MakeRequest(const Aws::AmazonWebServiceRequest& request,
  44. const Aws::Endpoint::AWSEndpoint& endpoint,
  45. Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
  46. const char* signerName /* = Aws::Auth::NULL_SIGNER */,
  47. const char* signerRegionOverride /* = nullptr */,
  48. const char* signerServiceNameOverride /* = nullptr */) const
  49. {
  50. const Aws::Http::URI& uri = endpoint.GetURI();
  51. if (endpoint.GetAttributes()) {
  52. signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
  53. if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
  54. signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
  55. }
  56. if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
  57. signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
  58. }
  59. if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
  60. signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
  61. }
  62. }
  63. return MakeRequest(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride);
  64. }
  65. JsonOutcome AWSJsonClient::MakeRequest(const Aws::Endpoint::AWSEndpoint& endpoint,
  66. Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
  67. const char* signerName /* = Aws::Auth::NULL_SIGNER */,
  68. const char* signerRegionOverride /* = nullptr */,
  69. const char* signerServiceNameOverride /* = nullptr */) const
  70. {
  71. const Aws::Http::URI& uri = endpoint.GetURI();
  72. if (endpoint.GetAttributes()) {
  73. signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
  74. if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
  75. signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
  76. }
  77. if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
  78. signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
  79. }
  80. if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
  81. signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
  82. }
  83. }
  84. return MakeRequest(uri, method, signerName, signerRegionOverride, signerServiceNameOverride);
  85. }
  86. JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
  87. const Aws::AmazonWebServiceRequest& request,
  88. Http::HttpMethod method,
  89. const char* signerName,
  90. const char* signerRegionOverride,
  91. const char* signerServiceNameOverride) const
  92. {
  93. HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride));
  94. if (!httpOutcome.IsSuccess())
  95. {
  96. return JsonOutcome(std::move(httpOutcome));
  97. }
  98. if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
  99. //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
  100. return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()),
  101. httpOutcome.GetResult()->GetHeaders(),
  102. httpOutcome.GetResult()->GetResponseCode()));
  103. else
  104. return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
  105. }
  106. JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
  107. Http::HttpMethod method,
  108. const char* signerName,
  109. const char* requestName,
  110. const char* signerRegionOverride,
  111. const char* signerServiceNameOverride) const
  112. {
  113. HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride));
  114. if (!httpOutcome.IsSuccess())
  115. {
  116. return JsonOutcome(std::move(httpOutcome));
  117. }
  118. if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
  119. {
  120. JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
  121. if (!jsonValue.WasParseSuccessful())
  122. {
  123. return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
  124. }
  125. //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
  126. return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
  127. httpOutcome.GetResult()->GetHeaders(),
  128. httpOutcome.GetResult()->GetResponseCode()));
  129. }
  130. return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
  131. }
  132. JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const
  133. {
  134. // request is assumed to be signed
  135. std::shared_ptr<HttpResponse> httpResponse = MakeHttpRequest(request);
  136. if (DoesResponseGenerateError(httpResponse))
  137. {
  138. AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response");
  139. auto error = BuildAWSError(httpResponse);
  140. return JsonOutcome(std::move(error));
  141. }
  142. AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned successful response.");
  143. HttpResponseOutcome httpOutcome(std::move(httpResponse));
  144. if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
  145. {
  146. JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
  147. if (!jsonValue.WasParseSuccessful())
  148. {
  149. return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
  150. }
  151. //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
  152. return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
  153. httpOutcome.GetResult()->GetHeaders(),
  154. httpOutcome.GetResult()->GetResponseCode()));
  155. }
  156. return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
  157. }
  158. AWSError<CoreErrors> AWSJsonClient::BuildAWSError(
  159. const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const
  160. {
  161. AWSError<CoreErrors> error;
  162. if (httpResponse->HasClientError())
  163. {
  164. bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false;
  165. error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable);
  166. }
  167. else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1)
  168. {
  169. auto responseCode = httpResponse->GetResponseCode();
  170. auto errorCode = AWSClient::GuessBodylessErrorType(responseCode);
  171. Aws::StringStream ss;
  172. ss << "No response body.";
  173. error = AWSError<CoreErrors>(errorCode, "", ss.str(),
  174. IsRetryableHttpResponseCode(responseCode));
  175. }
  176. else
  177. {
  178. assert(httpResponse->GetResponseCode() != HttpResponseCode::OK);
  179. error = GetErrorMarshaller()->Marshall(*httpResponse);
  180. }
  181. error.SetResponseHeaders(httpResponse->GetHeaders());
  182. error.SetResponseCode(httpResponse->GetResponseCode());
  183. error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost());
  184. AWS_LOGSTREAM_ERROR(AWS_JSON_CLIENT_LOG_TAG, error);
  185. return error;
  186. }