azure-core
http.hpp
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // SPDX-License-Identifier: MIT
3 
9 #pragma once
10 
13 #include "azure/core/exception.hpp"
16 #include "azure/core/internal/contract.hpp"
18 #include "azure/core/nullable.hpp"
19 #include "azure/core/url.hpp"
20 
21 #include <algorithm>
22 #include <cstdint>
23 #include <functional>
24 #include <map>
25 #include <memory>
26 #include <stdexcept>
27 #include <string>
28 #include <unordered_set>
29 #include <vector>
30 
31 #if defined(TESTING_BUILD)
32 // Define the class used from tests to validate retry enabled
33 namespace Azure { namespace Core { namespace Test {
34  class TestHttp_getters_Test;
35  class TestHttp_query_parameter_Test;
36  class TestHttp_RequestStartTry_Test;
37  class TestURL_getters_Test;
38  class TestURL_query_parameter_Test;
39  class TransportAdapter_headWithStream_Test;
40  class TransportAdapter_putWithStream_Test;
41  class TransportAdapter_deleteRequestWithStream_Test;
42  class TransportAdapter_patchWithStream_Test;
43  class TransportAdapter_putWithStreamOnFail_Test;
44  class TransportAdapter_SizePutFromFile_Test;
45  class TransportAdapter_SizePutFromFileDefault_Test;
46  class TransportAdapter_SizePutFromFileBiggerPage_Test;
47 }}} // namespace Azure::Core::Test
48 #endif
49 
50 namespace Azure { namespace Core { namespace Http {
51 
52  /********************* Exceptions **********************/
57  public:
66  explicit TransportException(std::string const& what) : Azure::Core::RequestFailedException(what)
67  {
68  }
69  };
70 
76  struct HttpRange final
77  {
82  int64_t Offset = 0;
83 
89  };
90 
94  class HttpMethod final {
95  public:
103  explicit HttpMethod(std::string value) : m_value(std::move(value)) {}
104 
111  bool operator==(const HttpMethod& other) const { return m_value == other.m_value; }
112 
119  bool operator!=(const HttpMethod& other) const { return !(*this == other); }
120 
124  const std::string& ToString() const { return m_value; }
125 
131 
137 
143 
149 
155 
161 
162  private:
163  std::string m_value;
164  }; // extensible enum HttpMethod
165 
166  namespace Policies { namespace _internal {
167  class RetryPolicy;
168  }} // namespace Policies::_internal
169 
176  class Request final {
177  friend class Azure::Core::Http::Policies::_internal::RetryPolicy;
178 #if defined(TESTING_BUILD)
179  // make tests classes friends to validate set Retry
180  friend class Azure::Core::Test::TestHttp_getters_Test;
181  friend class Azure::Core::Test::TestHttp_query_parameter_Test;
182  friend class Azure::Core::Test::TestHttp_RequestStartTry_Test;
183  friend class Azure::Core::Test::TestURL_getters_Test;
184  friend class Azure::Core::Test::TestURL_query_parameter_Test;
185  // make tests classes friends to validate private Request ctor that takes both stream and bool
186  friend class Azure::Core::Test::TransportAdapter_headWithStream_Test;
187  friend class Azure::Core::Test::TransportAdapter_putWithStream_Test;
188  friend class Azure::Core::Test::TransportAdapter_deleteRequestWithStream_Test;
189  friend class Azure::Core::Test::TransportAdapter_patchWithStream_Test;
190  friend class Azure::Core::Test::TransportAdapter_putWithStreamOnFail_Test;
191  friend class Azure::Core::Test::TransportAdapter_SizePutFromFile_Test;
192  friend class Azure::Core::Test::TransportAdapter_SizePutFromFileDefault_Test;
193  friend class Azure::Core::Test::TransportAdapter_SizePutFromFileBiggerPage_Test;
194 #endif
195 
196  private:
197  HttpMethod m_method;
198  Url m_url;
199  CaseInsensitiveMap m_headers;
200  CaseInsensitiveMap m_retryHeaders;
201 
202  Azure::Core::IO::BodyStream* m_bodyStream;
203 
204  // flag to know where to insert header
205  bool m_retryModeEnabled{false};
206  bool m_shouldBufferResponse{true};
207 
208  // Expected to be called by a Retry policy to reset all headers set after this function was
209  // previously called
210  void StartTry();
211 
212  public:
222  explicit Request(
223  HttpMethod httpMethod,
224  Url url,
225  Azure::Core::IO::BodyStream* bodyStream,
226  bool shouldBufferResponse)
227  : m_method(std::move(httpMethod)), m_url(std::move(url)), m_bodyStream(bodyStream),
228  m_retryModeEnabled(false), m_shouldBufferResponse(shouldBufferResponse)
229  {
230  AZURE_ASSERT_MSG(bodyStream, "The bodyStream pointer cannot be null.");
231  }
232 
240  explicit Request(HttpMethod httpMethod, Url url, Azure::Core::IO::BodyStream* bodyStream)
241  : Request(httpMethod, std::move(url), bodyStream, true)
242  {
243  }
244 
253  explicit Request(HttpMethod httpMethod, Url url, bool shouldBufferResponse);
254 
261  explicit Request(HttpMethod httpMethod, Url url);
262 
274  void SetHeader(std::string const& name, std::string const& value);
275 
284  Azure::Nullable<std::string> GetHeader(std::string const& name);
285 
291  void RemoveHeader(std::string const& name);
292 
293  // Methods used by transport layer (and logger) to send request
298  HttpMethod const& GetMethod() const;
299 
307 
312  Azure::Core::IO::BodyStream* GetBodyStream() { return this->m_bodyStream; }
313 
318  bool ShouldBufferResponse() { return this->m_shouldBufferResponse; }
319 
324  Url& GetUrl() { return this->m_url; }
325 
330  Url const& GetUrl() const { return this->m_url; }
331  };
332 
333  namespace _detail {
334  struct RawResponseHelpers final
335  {
346  static void InsertHeaderWithValidation(
347  CaseInsensitiveMap& headers,
348  std::string const& headerName,
349  std::string const& headerValue);
350 
351  static void inline SetHeader(
353  uint8_t const* const first,
354  uint8_t const* const last)
355  {
356  // get name and value from header
357  auto start = first;
358  auto end = std::find(start, last, ':');
359 
360  if (end == last)
361  {
362  throw std::invalid_argument("Invalid header. No delimiter ':' found.");
363  }
364 
365  // Always toLower() headers
366  auto headerName
367  = Azure::Core::_internal::StringExtensions::ToLower(std::string(start, end));
368  start = end + 1; // start value
369  while (start < last && (*start == ' ' || *start == '\t'))
370  {
371  ++start;
372  }
373 
374  end = std::find(start, last, '\r');
375  auto headerValue = std::string(start, end); // remove \r
376 
377  response.SetHeader(headerName, headerValue);
378  }
379  };
380  } // namespace _detail
381 
382  namespace _internal {
383 
384  struct HttpShared final
385  {
386  AZ_CORE_DLLEXPORT static char const ContentType[];
387  AZ_CORE_DLLEXPORT static char const ApplicationJson[];
388  AZ_CORE_DLLEXPORT static char const Accept[];
389  AZ_CORE_DLLEXPORT static char const MsRequestId[];
390  AZ_CORE_DLLEXPORT static char const MsClientRequestId[];
391 
392  static inline std::string GetHeaderOrEmptyString(
393  Azure::Core::CaseInsensitiveMap const& headers,
394  std::string const& headerName)
395  {
396  auto header = headers.find(headerName);
397  if (header != headers.end())
398  {
399  return header->second; // second is the header value.
400  }
401  return {}; // empty string
402  }
403  };
404  } // namespace _internal
405 
406 }}} // namespace Azure::Core::Http
Azure::Core::Http::TransportException
An error while sending the HTTP request with the transport adapter.
Definition: http.hpp:56
body_stream.hpp
BodyStream is used to read data to/from a service.
Azure::Core::Http::Request::Request
Request(HttpMethod httpMethod, Url url, Azure::Core::IO::BodyStream *bodyStream)
Constructs a Request.
Definition: http.hpp:240
Azure::Core::Http::HttpMethod::Head
AZ_CORE_DLLEXPORT static const HttpMethod Head
The representation of a HEAD HTTP method based on RFC 7231.
Definition: http.hpp:136
AZ_CORE_DLLEXPORT
#define AZ_CORE_DLLEXPORT
Applies DLL export attribute, when applicable.
Definition: dll_import_export.hpp:93
Azure::Core::Http::HttpRange::Length
Azure::Nullable< int64_t > Length
The size of the HTTP Range.
Definition: http.hpp:88
Azure::Core::Http::HttpMethod::Delete
AZ_CORE_DLLEXPORT static const HttpMethod Delete
The representation of a DELETE HTTP method based on RFC 7231.
Definition: http.hpp:154
raw_response.hpp
Define the HTTP raw response.
Azure::Core::IO::BodyStream
Used to read data to/from a service.
Definition: body_stream.hpp:32
Azure::Core::Http::Request::GetUrl
Url & GetUrl()
Get URL.
Definition: http.hpp:324
Azure::Core::Http::HttpMethod::operator!=
bool operator!=(const HttpMethod &other) const
Compares two instances of HttpMethod for equality.
Definition: http.hpp:119
Azure::Core::Http::Request::GetHeader
Azure::Nullable< std::string > GetHeader(std::string const &name)
Gets a specific HTTP header from an Azure::Core::Http::Request.
Definition: request.cpp:25
Azure::Core::Http::Request::GetUrl
Url const & GetUrl() const
Get URL.
Definition: http.hpp:330
Azure::Core::Http::TransportException::TransportException
TransportException(std::string const &what)
Constructs TransportException with a message string.
Definition: http.hpp:66
Azure::Nullable< int64_t >
Azure::Core::Http::HttpMethod::Post
AZ_CORE_DLLEXPORT static const HttpMethod Post
The representation of a POST HTTP method based on RFC 7231.
Definition: http.hpp:142
http_status_code.hpp
HTTP status code definition.
Azure::Core::Http::Request::SetHeader
void SetHeader(std::string const &name, std::string const &value)
Set an HTTP header to the Azure::Core::Http::Request.
Definition: request.cpp:43
Azure::Core::Http::HttpRange
The range of bytes within an HTTP resource.
Definition: http.hpp:77
Azure::Core::Http::Request::ShouldBufferResponse
bool ShouldBufferResponse()
A value indicating whether the returned raw response for this request will be buffered within a memor...
Definition: http.hpp:318
Azure::Core::Http::Request
A request message from a client to a server.
Definition: http.hpp:176
Azure::Core::Http::Request::GetMethod
HttpMethod const & GetMethod() const
Get HttpMethod.
Definition: request.cpp:71
Azure::Core::Http::HttpMethod::HttpMethod
HttpMethod(std::string value)
Constructs HttpMethod from string.
Definition: http.hpp:103
url.hpp
Uniform Resource Locator (URL).
Azure::Core::Http::RawResponse
After receiving and interpreting a request message, a server responds with an HTTP response message.
Definition: raw_response.hpp:24
Azure::Core::Http::HttpMethod
The method to be performed on the resource identified by the Request.
Definition: http.hpp:94
Azure::Core::Http::Request::RemoveHeader
void RemoveHeader(std::string const &name)
Remove an HTTP header.
Definition: request.cpp:52
Azure
Azure SDK abstractions.
Definition: azure_assert.hpp:55
Azure::Core::Http::RawResponse::SetHeader
void SetHeader(std::string const &name, std::string const &value)
Set an HTTP header to the #RawResponse.
Definition: raw_response.cpp:22
Azure::Core::CaseInsensitiveMap
std::map< std::string, std::string, _internal::StringExtensions::CaseInsensitiveComparator > CaseInsensitiveMap
A type alias of std::map<std::string, std::string> with case-insensitive key comparison.
Definition: case_insensitive_containers.hpp:24
Azure::Core::RequestFailedException
An error while trying to send a request to Azure service.
Definition: exception.hpp:57
Azure::Core::Http::HttpMethod::operator==
bool operator==(const HttpMethod &other) const
Compares two instances of HttpMethod for equality.
Definition: http.hpp:111
dll_import_export.hpp
DLL export macro.
case_insensitive_containers.hpp
A map<string, string> with case-insensitive key comparison.
nullable.hpp
Manages an optional contained value, i.e. a value that may or may not be present.
exception.hpp
Define RequestFailedException. It is used by HTTP exceptions.
Azure::Core::Http::Request::GetHeaders
CaseInsensitiveMap GetHeaders() const
Get HTTP headers.
Definition: request.cpp:73
Azure::Core::Http::HttpMethod::ToString
const std::string & ToString() const
Returns the HttpMethod represented as a string.
Definition: http.hpp:124
Azure::Core::Http::HttpMethod::Put
AZ_CORE_DLLEXPORT static const HttpMethod Put
The representation of a PUT HTTP method based on RFC 7231.
Definition: http.hpp:148
Azure::Core::Http::HttpMethod::Get
AZ_CORE_DLLEXPORT static const HttpMethod Get
The representation of a GET HTTP method based on RFC 7231.
Definition: http.hpp:130
Azure::Core::Http::Request::GetBodyStream
Azure::Core::IO::BodyStream * GetBodyStream()
Get HTTP body as Azure::Core::IO::BodyStream.
Definition: http.hpp:312
Azure::Core::Http::HttpMethod::Patch
AZ_CORE_DLLEXPORT static const HttpMethod Patch
The representation of a PATCH HTTP method based on RFC 5789.
Definition: http.hpp:160
Azure::Core::Url
Represents the location where a request will be performed.
Definition: url.hpp:47
Azure::Core::Http::HttpRange::Offset
int64_t Offset
The starting point of the HTTP Range.
Definition: http.hpp:82
Azure::Core::Http::Request::Request
Request(HttpMethod httpMethod, Url url, Azure::Core::IO::BodyStream *bodyStream, bool shouldBufferResponse)
Construct an Azure::Core::Http::Request.
Definition: http.hpp:222