HttpRequestJob.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <Framework/AWSApiJob.h>
  10. #include <Framework/HttpRequestJobConfig.h>
  11. #include <Framework/Util.h>
  12. namespace Aws
  13. {
  14. namespace Client
  15. {
  16. class AWSAuthSigner;
  17. }
  18. namespace Http
  19. {
  20. class HttpClient;
  21. class HttpRequest;
  22. class HttpResponse;
  23. }
  24. }
  25. namespace AWSCore
  26. {
  27. /////////////////////////////////////////////
  28. // HTTP Request run on a background thread
  29. /////////////////////////////////////////////
  30. class HttpRequestJob
  31. : public AwsApiJob
  32. {
  33. public:
  34. enum class HttpMethod
  35. {
  36. HTTP_GET,
  37. HTTP_POST,
  38. HTTP_DELETE,
  39. HTTP_PUT,
  40. HTTP_HEAD,
  41. HTTP_PATCH
  42. };
  43. enum class HeaderField
  44. {
  45. DATE,
  46. AWS_DATE,
  47. AWS_SECURITY_TOKEN,
  48. ACCEPT,
  49. ACCEPT_CHAR_SET,
  50. ACCEPT_ENCODING,
  51. AUTHORIZATION,
  52. AWS_AUTHORIZATION,
  53. COOKIE,
  54. CONTENT_LENGTH,
  55. CONTENT_TYPE,
  56. USER_AGENT,
  57. VIA,
  58. HOST,
  59. AMZ_TARGET,
  60. X_AMZ_EXPIRES,
  61. CONTENT_MD5,
  62. };
  63. class Response
  64. {
  65. public:
  66. const AZStd::string& GetResponseBody() const;
  67. int GetResponseCode() const;
  68. const std::shared_ptr<Aws::Http::HttpResponse>& GetUnderlyingResponse() const;
  69. private:
  70. std::shared_ptr<Aws::Http::HttpResponse> m_response;
  71. AZStd::string m_responseBody;
  72. int m_responseCode = 0;
  73. friend class HttpRequestJob;
  74. };
  75. using SuccessFn = AZStd::function<void(const AZStd::shared_ptr<Response>& response)>;
  76. using FailureFn = AZStd::function<void(const AZStd::shared_ptr<Response>& response)>;
  77. using StringMap = AZStd::unordered_map<AZStd::string, AZStd::string>;
  78. public:
  79. // To use a different allocator, extend this class and use this macro.
  80. AZ_CLASS_ALLOCATOR(HttpRequestJob, AZ::SystemAllocator);
  81. using IConfig = IHttpRequestJobConfig;
  82. using Config = HttpRequestJobConfig;
  83. static Config* GetDefaultConfig()
  84. {
  85. static AwsApiJobConfigHolder<Config> s_configHolder{};
  86. return s_configHolder.GetConfig(AwsApiJob::GetDefaultConfig());
  87. }
  88. static void StaticInit();
  89. static void StaticShutdown();
  90. public:
  91. HttpRequestJob(bool isAutoDelete, IConfig* config)
  92. : AwsApiJob(isAutoDelete, config)
  93. , m_readRateLimiter(config->GetReadRateLimiter())
  94. , m_writeRateLimiter(config->GetWriteRateLimiter())
  95. , m_httpClient(config->GetHttpClient())
  96. {
  97. SetRequestHeader(HeaderField::USER_AGENT, Util::ToAZString(config->GetUserAgent()));
  98. }
  99. /// Get and set the URL for this request
  100. void SetUrl(AZStd::string url);
  101. const AZStd::string& GetUrl() const;
  102. /// Get and set the HTTP method for this request
  103. void SetMethod(HttpMethod method);
  104. bool SetMethod(const AZStd::string& method);
  105. HttpMethod GetMethod() const;
  106. /// Get and set headers for the HTTP request
  107. void SetRequestHeader(AZStd::string key, AZStd::string value);
  108. bool GetRequestHeader(const AZStd::string& key, AZStd::string* result = nullptr);
  109. /// Get and set pre-defined header fields. Equivalent to manually setting the corresponding header field, e.g.
  110. /// HeaderField::CONTENT_LENGTH maps to "Content-Length".
  111. void SetRequestHeader(HeaderField field, AZStd::string value);
  112. bool GetRequestHeader(HeaderField field, AZStd::string* result = nullptr);
  113. /// Get the collection of all request headers.
  114. StringMap& GetRequestHeaders();
  115. const StringMap& GetRequestHeaders() const;
  116. /// Syntactic sugar to set popular headers. Equivalent to manually setting the corresponding header field.
  117. void SetAccept(AZStd::string accept);
  118. void SetAcceptCharSet(AZStd::string accept);
  119. void SetContentLength(AZStd::string contentLength);
  120. void SetContentType(AZStd::string contentType);
  121. /// Get and set AWS authorization signer for the request
  122. void SetAWSAuthSigner(const std::shared_ptr<Aws::Client::AWSAuthSigner>& authSigner);
  123. const std::shared_ptr<Aws::Client::AWSAuthSigner>& GetAWSAuthSigner() const;
  124. /// Get and set the body for the HTTP request. (You are responsible for setting the Content-Length header.)
  125. void SetBody(AZStd::string body);
  126. const AZStd::string& GetBody() const;
  127. AZStd::string& GetBody();
  128. /// Set callback functions for success and failure. These will be executed on the main thread.
  129. template<typename SuccessCallbackT, typename FailureCallbackT>
  130. void SetCallbacks(SuccessCallbackT&& successCB, FailureCallbackT&& failureCB);
  131. /// Converts an HttpMethod to a string. Used for debug output.
  132. static const char* HttpMethodToString(HttpMethod);
  133. static const char* HttpMethodToString(Aws::Http::HttpMethod);
  134. /// Converts a string to an HttpMethod.
  135. static AZStd::optional<HttpMethod> StringToHttpMethod(const AZStd::string& method);
  136. protected:
  137. /// Override to provide a custom instantiation of the HttpRequest.
  138. /// The default implementation uses the URL and method specified in this class.
  139. /// This is required mainly because Aws::Http::HttpRequest demands that these parameters be configured at the time of construction.
  140. /// You can also use this opportunity to set properties of the HttpRequestJob you want reflected in the request.
  141. /// WARNING: This gets called on the job's thread, so observe thread safety precautions.
  142. virtual std::shared_ptr<Aws::Http::HttpRequest> InitializeRequest();
  143. /// Override to customize HTTP request right before it is sent.
  144. /// Configuration specified in this class will already have been configured in the request.
  145. /// WARNING: This gets called on the job's thread, so observe thread safety precautions.
  146. virtual void CustomizeRequest(const std::shared_ptr<Aws::Http::HttpRequest>& request)
  147. {
  148. AZ_UNUSED(request);
  149. };
  150. /// Override to process the response to the HTTP request before callbacks are fired.
  151. /// WARNING: This gets called on the job's thread, so observe thread safety precautions.
  152. virtual void ProcessResponse(const std::shared_ptr<Aws::Http::HttpResponse>& response)
  153. {
  154. AZ_UNUSED(response);
  155. };
  156. private:
  157. /// Runs the HTTP request on the Job's thread.
  158. void Process() override;
  159. private:
  160. std::shared_ptr<Aws::Utils::RateLimits::RateLimiterInterface> m_readRateLimiter;
  161. std::shared_ptr<Aws::Utils::RateLimits::RateLimiterInterface> m_writeRateLimiter;
  162. std::shared_ptr<Aws::Http::HttpClient> m_httpClient;
  163. std::shared_ptr<Aws::Client::AWSAuthSigner> m_awsAuthSigner;
  164. SuccessFn m_successCallback;
  165. FailureFn m_failureCallback;
  166. StringMap m_requestHeaders;
  167. AZStd::string m_url;
  168. AZStd::string m_requestBody;
  169. HttpMethod m_method = HttpMethod::HTTP_GET;
  170. };
  171. template<typename SuccessCallbackT, typename FailureCallbackT>
  172. inline void HttpRequestJob::SetCallbacks(SuccessCallbackT&& successCB, FailureCallbackT&& failureCB)
  173. {
  174. m_successCallback = AZStd::forward<SuccessCallbackT>(successCB);
  175. m_failureCallback = AZStd::forward<FailureCallbackT>(failureCB);
  176. }
  177. } // namespace AWSCore