azure-core
policy.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 
12 #include "azure/core/context.hpp"
15 #include "azure/core/http/http.hpp"
17 #include "azure/core/internal/input_sanitizer.hpp"
19 #include "azure/core/uuid.hpp"
20 
21 #include <atomic>
22 #include <chrono>
23 #include <cstddef>
24 #include <map>
25 #include <memory>
26 #include <mutex>
27 #include <set>
28 #include <string>
29 #include <utility>
30 #include <vector>
31 
39 extern std::shared_ptr<Azure::Core::Http::HttpTransport> AzureSdkGetCustomHttpTransport();
40 
41 namespace Azure { namespace Core { namespace Http { namespace Policies {
42 
43  namespace _detail {
44  std::shared_ptr<HttpTransport> GetTransportAdapter();
45  AZ_CORE_DLLEXPORT extern Azure::Core::CaseInsensitiveSet const g_defaultAllowedHttpHeaders;
46  } // namespace _detail
47 
52  struct TelemetryOptions final
53  {
61  std::string ApplicationId;
62 
67  std::shared_ptr<Azure::Core::Tracing::TracerProvider> TracingProvider{
69  };
70 
77  struct RetryOptions final
78  {
83  int32_t MaxRetries = 3;
84 
90  std::chrono::milliseconds RetryDelay = std::chrono::seconds(4);
91 
97  std::chrono::milliseconds MaxRetryDelay = std::chrono::minutes(2);
98 
103  std::set<HttpStatusCode> StatusCodes{
109  };
110  };
111 
117  struct LogOptions final
118  {
123  std::set<std::string> AllowedHttpQueryParameters;
124 
129  Azure::Core::CaseInsensitiveSet AllowedHttpHeaders = _detail::g_defaultAllowedHttpHeaders;
130  };
131 
135  struct TransportOptions final
136  {
151  std::shared_ptr<HttpTransport> Transport = _detail::GetTransportAdapter();
152  };
153 
154  class NextHttpPolicy;
155 
162  class HttpPolicy {
163  public:
164  // If we get a response that goes up the stack
165  // Any errors in the pipeline throws an exception
166  // At the top of the pipeline we might want to turn certain responses into exceptions
167 
178  virtual std::unique_ptr<RawResponse> Send(
179  Request& request,
180  NextHttpPolicy nextPolicy,
181  Context const& context) const = 0;
182 
187  virtual ~HttpPolicy() {}
188 
193  virtual std::unique_ptr<HttpPolicy> Clone() const = 0;
194 
195  protected:
200  HttpPolicy() = default;
201 
207  HttpPolicy(const HttpPolicy& other) = default;
208 
215  HttpPolicy& operator=(const HttpPolicy& other) = default;
216 
222  HttpPolicy(HttpPolicy&& other) = default;
223  };
224 
234  class NextHttpPolicy final {
235  const size_t m_index;
236  const std::vector<std::unique_ptr<HttpPolicy>>& m_policies;
237 
238  public:
247  explicit NextHttpPolicy(size_t index, const std::vector<std::unique_ptr<HttpPolicy>>& policies)
248  : m_index(index), m_policies(policies)
249  {
250  }
251 
261  std::unique_ptr<RawResponse> Send(Request& request, Context const& context);
262  };
263 
264  namespace _internal {
265 
270  class TransportPolicy final : public HttpPolicy {
271  private:
272  TransportOptions m_options;
273 
274  public:
280  explicit TransportPolicy(TransportOptions options = TransportOptions())
281  : m_options(std::move(options))
282  {
283  }
284 
285  std::unique_ptr<HttpPolicy> Clone() const override
286  {
287  return std::make_unique<TransportPolicy>(*this);
288  }
289 
290  std::unique_ptr<RawResponse> Send(
291  Request& request,
292  NextHttpPolicy nextPolicy,
293  Context const& context) const override;
294  };
295 
299  class RetryPolicy
300 #if !defined(TESTING_BUILD)
301  final
302 #endif
303  : public HttpPolicy {
304  private:
305  RetryOptions m_retryOptions;
306 
307  public:
313  explicit RetryPolicy(RetryOptions options) : m_retryOptions(std::move(options)) {}
314 
315  std::unique_ptr<HttpPolicy> Clone() const override
316  {
317  return std::make_unique<RetryPolicy>(*this);
318  }
319 
320  std::unique_ptr<RawResponse> Send(
321  Request& request,
322  NextHttpPolicy nextPolicy,
323  Context const& context) const final;
324 
336  static int32_t GetRetryCount(Context const& context);
337 
338  protected:
339  virtual bool ShouldRetryOnTransportFailure(
340  RetryOptions const& retryOptions,
341  int32_t attempt,
342  std::chrono::milliseconds& retryAfter,
343  double jitterFactor = -1) const;
344 
345  virtual bool ShouldRetryOnResponse(
346  RawResponse const& response,
347  RetryOptions const& retryOptions,
348  int32_t attempt,
349  std::chrono::milliseconds& retryAfter,
350  double jitterFactor = -1) const;
351  };
352 
359  class RequestIdPolicy final : public HttpPolicy {
360  private:
361  constexpr static const char* RequestIdHeader = "x-ms-client-request-id";
362 
363  public:
368  explicit RequestIdPolicy() {}
369 
370  std::unique_ptr<HttpPolicy> Clone() const override
371  {
372  return std::make_unique<RequestIdPolicy>(*this);
373  }
374 
375  std::unique_ptr<RawResponse> Send(
376  Request& request,
377  NextHttpPolicy nextPolicy,
378  Context const& context) const override
379  {
380  auto uuid = Uuid::CreateUuid().ToString();
381 
382  request.SetHeader(RequestIdHeader, uuid);
383  return nextPolicy.Send(request, context);
384  }
385  };
386 
395  class RequestActivityPolicy final : public HttpPolicy {
396  private:
397  Azure::Core::_internal::InputSanitizer m_inputSanitizer;
398 
399  public:
403  // explicit RequestActivityPolicy() = default;
409  explicit RequestActivityPolicy(Azure::Core::_internal::InputSanitizer const& inputSanitizer)
410  : m_inputSanitizer(inputSanitizer)
411  {
412  }
413 
414  std::unique_ptr<HttpPolicy> Clone() const override
415  {
416  return std::make_unique<RequestActivityPolicy>(*this);
417  }
418 
419  std::unique_ptr<RawResponse> Send(
420  Request& request,
421  NextHttpPolicy nextPolicy,
422  Context const& context) const override;
423  };
424 
432  class TelemetryPolicy final : public HttpPolicy {
433  private:
434  std::string const m_telemetryId;
435 
436  static std::string BuildTelemetryId(
437  std::string const& componentName,
438  std::string const& componentVersion,
439  std::string const& applicationId);
440 
441  public:
449  explicit TelemetryPolicy(
450  std::string const& componentName,
451  std::string const& componentVersion,
452  TelemetryOptions options = TelemetryOptions())
453  : m_telemetryId(BuildTelemetryId(componentName, componentVersion, options.ApplicationId))
454  {
455  }
456 
457  std::unique_ptr<HttpPolicy> Clone() const override
458  {
459  return std::make_unique<TelemetryPolicy>(*this);
460  }
461 
462  std::unique_ptr<RawResponse> Send(
463  Request& request,
464  NextHttpPolicy nextPolicy,
465  Context const& context) const override;
466  };
467 
472  class BearerTokenAuthenticationPolicy final : public HttpPolicy {
473  private:
474  std::shared_ptr<Credentials::TokenCredential const> const m_credential;
475  Credentials::TokenRequestContext m_tokenRequestContext;
476 
477  mutable Credentials::AccessToken m_accessToken;
478  mutable std::mutex m_accessTokenMutex;
479 
480  BearerTokenAuthenticationPolicy(BearerTokenAuthenticationPolicy const&) = delete;
481  void operator=(BearerTokenAuthenticationPolicy const&) = delete;
482 
483  public:
490  explicit BearerTokenAuthenticationPolicy(
491  std::shared_ptr<Credentials::TokenCredential const> credential,
492  Credentials::TokenRequestContext tokenRequestContext)
493  : m_credential(std::move(credential)),
494  m_tokenRequestContext(std::move(tokenRequestContext))
495  {
496  }
497 
498  std::unique_ptr<HttpPolicy> Clone() const override
499  {
500  return std::make_unique<BearerTokenAuthenticationPolicy>(
501  m_credential, m_tokenRequestContext);
502  }
503 
504  std::unique_ptr<RawResponse> Send(
505  Request& request,
506  NextHttpPolicy nextPolicy,
507  Context const& context) const override;
508  };
509 
516  class LogPolicy final : public HttpPolicy {
517  LogOptions m_options;
518  Azure::Core::_internal::InputSanitizer m_inputSanitizer;
519 
520  public:
525  explicit LogPolicy(LogOptions options)
526  : m_options(std::move(options)),
527  m_inputSanitizer(m_options.AllowedHttpQueryParameters, m_options.AllowedHttpHeaders)
528  {
529  }
530 
531  std::unique_ptr<HttpPolicy> Clone() const override
532  {
533  return std::make_unique<LogPolicy>(*this);
534  }
535 
536  std::unique_ptr<RawResponse> Send(
537  Request& request,
538  NextHttpPolicy nextPolicy,
539  Context const& context) const override;
540  };
541  } // namespace _internal
542 }}}} // namespace Azure::Core::Http::Policies
Azure::Core::Uuid::CreateUuid
static Uuid CreateUuid()
Creates a new random UUID.
Definition: uuid.cpp:50
credentials.hpp
Credentials used for authentication with many (not all) Azure SDK client libraries.
Azure::Core::Context::GetTracerProvider
std::shared_ptr< Tracing::TracerProvider > GetTracerProvider()
Returns the tracer provider for the current context.
Definition: context.hpp:259
Azure::Core::Http::Policies::HttpPolicy::Send
virtual std::unique_ptr< RawResponse > Send(Request &request, NextHttpPolicy nextPolicy, Context const &context) const =0
Applies this HTTP policy.
AZ_CORE_DLLEXPORT
#define AZ_CORE_DLLEXPORT
Applies DLL export attribute, when applicable.
Definition: dll_import_export.hpp:93
Azure::Core::Http::Policies::TransportOptions::Transport
std::shared_ptr< HttpTransport > Transport
Azure::Core::Http::HttpTransport that the transport policy will use to send and receive requests and ...
Definition: policy.hpp:151
Azure::Core::Http::Policies::NextHttpPolicy
The next HTTP policy in the stack sequence of policies.
Definition: policy.hpp:234
Azure::Core::Http::Policies::HttpPolicy::Clone
virtual std::unique_ptr< HttpPolicy > Clone() const =0
Creates a clone of this HttpPolicy.
context.hpp
Context for canceling long running operations.
Azure::Core::Http::Policies::TransportOptions
HTTP transport options parameterize the HTTP transport adapter being used.
Definition: policy.hpp:136
Azure::Core::Http::Policies::HttpPolicy::HttpPolicy
HttpPolicy(HttpPolicy &&other)=default
Contructs HttpPolicy by moving other HttpPolicy.
Azure::Core::Http::Policies::RetryOptions
The set of options that can be specified to influence how retry attempts are made,...
Definition: policy.hpp:78
Azure::Core::Http::Policies::HttpPolicy::HttpPolicy
HttpPolicy(const HttpPolicy &other)=default
Constructs a copy of other HttpPolicy.
tracing.hpp
Handling log messages from Azure SDK.
Azure::Core::Http::Policies::TelemetryOptions::TracingProvider
std::shared_ptr< Azure::Core::Tracing::TracerProvider > TracingProvider
Specifies the default distributed tracing provider to use for this client. By default,...
Definition: policy.hpp:67
Azure::Core::Http::Policies::TelemetryOptions::ApplicationId
std::string ApplicationId
The Application ID is the last part of the user agent for telemetry.
Definition: policy.hpp:61
uuid.hpp
Universally unique identifier.
Azure::Core::Http::Policies::LogOptions
Log options that parameterize the information being logged.
Definition: policy.hpp:118
Azure::Core::Http::Policies::HttpPolicy::operator=
HttpPolicy & operator=(const HttpPolicy &other)=default
Assigns this HttpPolicy to copy the other.
Azure::Core::Http::Policies::HttpPolicy::HttpPolicy
HttpPolicy()=default
Constructs a default instance of HttpPolicy.
Azure::Core::Http::Policies::RetryOptions::StatusCodes
std::set< HttpStatusCode > StatusCodes
The HTTP status codes that indicate when an operation should be retried.
Definition: policy.hpp:103
Azure::Core::Http::HttpStatusCode::RequestTimeout
@ RequestTimeout
HTTP 408 Request Timeout.
Azure::Core::Http::HttpStatusCode::GatewayTimeout
@ GatewayTimeout
HTTP 504 Gateway Timeout.
Azure::Core::Http::Request
A request message from a client to a server.
Definition: http.hpp:176
Azure::Core::Http::HttpStatusCode::BadGateway
@ BadGateway
HTTP 502 Bad Gateway.
AzureSdkGetCustomHttpTransport
std::shared_ptr< Azure::Core::Http::HttpTransport > AzureSdkGetCustomHttpTransport()
Azure::Core::Http::Policies::NextHttpPolicy::NextHttpPolicy
NextHttpPolicy(size_t index, const std::vector< std::unique_ptr< HttpPolicy >> &policies)
Constructs an abstraction representing a next line in the stack sequence of policies,...
Definition: policy.hpp:247
Azure
Azure SDK abstractions.
Definition: azure_assert.hpp:55
http.hpp
HTTP request and response functionality.
Azure::Core::Http::Policies::RetryOptions::RetryDelay
std::chrono::milliseconds RetryDelay
The minimum permissible delay between retry attempts.
Definition: policy.hpp:90
Azure::Core::Uuid::ToString
std::string ToString()
Gets Uuid as a string.
Definition: uuid.cpp:20
Azure::Core::Http::Policies::RetryOptions::MaxRetryDelay
std::chrono::milliseconds MaxRetryDelay
The maximum permissible delay between retry attempts.
Definition: policy.hpp:97
dll_import_export.hpp
DLL export macro.
case_insensitive_containers.hpp
A map<string, string> with case-insensitive key comparison.
Azure::Core::CaseInsensitiveSet
std::set< std::string, _internal::StringExtensions::CaseInsensitiveComparator > CaseInsensitiveSet
A type alias of std::set<std::string> with case-insensitive element comparison.
Definition: case_insensitive_containers.hpp:31
Azure::Core::Http::Policies::NextHttpPolicy::Send
std::unique_ptr< RawResponse > Send(Request &request, Context const &context)
Applies this HTTP policy.
Definition: policy.cpp:13
Azure::Core::Http::Policies::LogOptions::AllowedHttpQueryParameters
std::set< std::string > AllowedHttpQueryParameters
HTTP query parameter names that are allowed to be logged.
Definition: policy.hpp:123
Azure::Core::Http::Policies::HttpPolicy
HTTP policy base class.
Definition: policy.hpp:162
transport.hpp
Utilities to be used by HTTP transport implementations.
Azure::Core::Http::Policies::LogOptions::AllowedHttpHeaders
Azure::Core::CaseInsensitiveSet AllowedHttpHeaders
HTTP header names that are allowed to be logged.
Definition: policy.hpp:129
Azure::Core::Http::HttpStatusCode::ServiceUnavailable
@ ServiceUnavailable
HTTP 503 Unavailable.
Azure::Core::Http::Policies::HttpPolicy::~HttpPolicy
virtual ~HttpPolicy()
Destructs HttpPolicy.
Definition: policy.hpp:187
Azure::Core::Context
A context is a node within a tree that represents deadlines and key/value pairs.
Definition: context.hpp:45
Azure::Core::Http::HttpStatusCode::InternalServerError
@ InternalServerError
HTTP 500 Internal Server Error.
Azure::Core::Http::Policies::TelemetryOptions
Telemetry options, used to configure telemetry parameters.
Definition: policy.hpp:53
Azure::Core::Context::ApplicationContext
static AZ_CORE_DLLEXPORT Context ApplicationContext
The application context (root).
Definition: context.hpp:276
Azure::Core::Http::Policies::RetryOptions::MaxRetries
int32_t MaxRetries
The maximum number of retry attempts before giving up.
Definition: policy.hpp:83