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/http/http_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  struct TransportOptions;
44  namespace _detail {
45  std::shared_ptr<HttpTransport> GetTransportAdapter(TransportOptions const& transportOptions);
46 
47  AZ_CORE_DLLEXPORT extern std::set<std::string> const g_defaultAllowedHttpQueryParameters;
48  AZ_CORE_DLLEXPORT extern CaseInsensitiveSet const g_defaultAllowedHttpHeaders;
49  } // namespace _detail
50 
55  struct TelemetryOptions final
56  {
64  std::string ApplicationId;
65 
70  std::shared_ptr<Azure::Core::Tracing::TracerProvider> TracingProvider;
71  };
72 
79  struct RetryOptions final
80  {
85  int32_t MaxRetries = 3;
86 
92  std::chrono::milliseconds RetryDelay = std::chrono::milliseconds(800);
93 
99  std::chrono::milliseconds MaxRetryDelay = std::chrono::seconds(60);
100 
105  std::set<HttpStatusCode> StatusCodes{
111  };
112  };
113 
119  struct LogOptions final
120  {
125  std::set<std::string> AllowedHttpQueryParameters = _detail::g_defaultAllowedHttpQueryParameters;
126 
131  CaseInsensitiveSet AllowedHttpHeaders = _detail::g_defaultAllowedHttpHeaders;
132  };
133 
137  struct TransportOptions final
138  {
149 
157 
165 
175 
188 
207  std::shared_ptr<HttpTransport> Transport;
208  };
209 
210  class NextHttpPolicy;
211 
218  class HttpPolicy {
219  public:
220  // If we get a response that goes up the stack
221  // Any errors in the pipeline throws an exception
222  // At the top of the pipeline we might want to turn certain responses into exceptions
223 
234  virtual std::unique_ptr<RawResponse> Send(
235  Request& request,
236  NextHttpPolicy nextPolicy,
237  Context const& context) const = 0;
238 
243  virtual ~HttpPolicy() {}
244 
249  virtual std::unique_ptr<HttpPolicy> Clone() const = 0;
250 
251  protected:
256  HttpPolicy() = default;
257 
263  HttpPolicy(const HttpPolicy& other) = default;
264 
271  HttpPolicy& operator=(const HttpPolicy& other) = default;
272 
278  HttpPolicy(HttpPolicy&& other) = default;
279  };
280 
290  class NextHttpPolicy final {
291  const size_t m_index;
292  const std::vector<std::unique_ptr<HttpPolicy>>& m_policies;
293 
294  public:
303  explicit NextHttpPolicy(size_t index, const std::vector<std::unique_ptr<HttpPolicy>>& policies)
304  : m_index(index), m_policies(policies)
305  {
306  }
307 
317  std::unique_ptr<RawResponse> Send(Request& request, Context const& context);
318  };
319 
320  namespace _internal {
321 
326  class TransportPolicy final : public HttpPolicy {
327  private:
328  TransportOptions m_options;
329 
330  public:
336  explicit TransportPolicy(TransportOptions const& options = TransportOptions());
337 
338  std::unique_ptr<HttpPolicy> Clone() const override
339  {
340  return std::make_unique<TransportPolicy>(*this);
341  }
342 
343  std::unique_ptr<RawResponse> Send(
344  Request& request,
345  NextHttpPolicy nextPolicy,
346  Context const& context) const override;
347  };
348 
352  class RetryPolicy
353 #if !defined(TESTING_BUILD)
354  final
355 #endif
356  : public HttpPolicy {
357  private:
358  RetryOptions m_retryOptions;
359 
360  public:
366  explicit RetryPolicy(RetryOptions options) : m_retryOptions(std::move(options)) {}
367 
368  std::unique_ptr<HttpPolicy> Clone() const override
369  {
370  return std::make_unique<RetryPolicy>(*this);
371  }
372 
373  std::unique_ptr<RawResponse> Send(
374  Request& request,
375  NextHttpPolicy nextPolicy,
376  Context const& context) const final;
377 
389  static int32_t GetRetryCount(Context const& context);
390 
391  protected:
392  virtual bool ShouldRetryOnTransportFailure(
393  RetryOptions const& retryOptions,
394  int32_t attempt,
395  std::chrono::milliseconds& retryAfter,
396  double jitterFactor = -1) const;
397 
398  virtual bool ShouldRetryOnResponse(
399  RawResponse const& response,
400  RetryOptions const& retryOptions,
401  int32_t attempt,
402  std::chrono::milliseconds& retryAfter,
403  double jitterFactor = -1) const;
404  };
405 
412  class RequestIdPolicy final : public HttpPolicy {
413  private:
414  constexpr static const char* RequestIdHeader = "x-ms-client-request-id";
415 
416  public:
421  explicit RequestIdPolicy() {}
422 
423  std::unique_ptr<HttpPolicy> Clone() const override
424  {
425  return std::make_unique<RequestIdPolicy>(*this);
426  }
427 
428  std::unique_ptr<RawResponse> Send(
429  Request& request,
430  NextHttpPolicy nextPolicy,
431  Context const& context) const override
432  {
433  if (!request.GetHeader(RequestIdHeader).HasValue())
434  {
435  auto const uuid = Uuid::CreateUuid().ToString();
436  request.SetHeader(RequestIdHeader, uuid);
437  }
438 
439  return nextPolicy.Send(request, context);
440  }
441  };
442 
451  class RequestActivityPolicy final : public HttpPolicy {
452  private:
453  Azure::Core::Http::_internal::HttpSanitizer m_httpSanitizer;
454 
455  public:
459  // explicit RequestActivityPolicy() = default;
465  explicit RequestActivityPolicy(
466  Azure::Core::Http::_internal::HttpSanitizer const& httpSanitizer)
467  : m_httpSanitizer(httpSanitizer)
468  {
469  }
470 
471  std::unique_ptr<HttpPolicy> Clone() const override
472  {
473  return std::make_unique<RequestActivityPolicy>(*this);
474  }
475 
476  std::unique_ptr<RawResponse> Send(
477  Request& request,
478  NextHttpPolicy nextPolicy,
479  Context const& context) const override;
480  };
481 
495  class TelemetryPolicy final : public HttpPolicy {
496  private:
497  std::string const m_telemetryId;
498 
499  public:
507  explicit TelemetryPolicy(
508  std::string const& packageName,
509  std::string const& packageVersion,
510  TelemetryOptions options = TelemetryOptions())
511  : m_telemetryId(Azure::Core::Http::_detail::UserAgentGenerator::GenerateUserAgent(
512  packageName,
513  packageVersion,
514  options.ApplicationId))
515  {
516  }
517 
518  std::unique_ptr<HttpPolicy> Clone() const override
519  {
520  return std::make_unique<TelemetryPolicy>(*this);
521  }
522 
523  std::unique_ptr<RawResponse> Send(
524  Request& request,
525  NextHttpPolicy nextPolicy,
526  Context const& context) const override;
527  };
528 
533  class BearerTokenAuthenticationPolicy final : public HttpPolicy {
534  private:
535  std::shared_ptr<Credentials::TokenCredential const> const m_credential;
536  Credentials::TokenRequestContext m_tokenRequestContext;
537 
538  mutable Credentials::AccessToken m_accessToken;
539  mutable std::mutex m_accessTokenMutex;
540 
541  BearerTokenAuthenticationPolicy(BearerTokenAuthenticationPolicy const&) = delete;
542  void operator=(BearerTokenAuthenticationPolicy const&) = delete;
543 
544  public:
551  explicit BearerTokenAuthenticationPolicy(
552  std::shared_ptr<Credentials::TokenCredential const> credential,
553  Credentials::TokenRequestContext tokenRequestContext)
554  : m_credential(std::move(credential)),
555  m_tokenRequestContext(std::move(tokenRequestContext))
556  {
557  }
558 
559  std::unique_ptr<HttpPolicy> Clone() const override
560  {
561  return std::make_unique<BearerTokenAuthenticationPolicy>(
562  m_credential, m_tokenRequestContext);
563  }
564 
565  std::unique_ptr<RawResponse> Send(
566  Request& request,
567  NextHttpPolicy nextPolicy,
568  Context const& context) const override;
569  };
570 
577  class LogPolicy final : public HttpPolicy {
578  LogOptions m_options;
579  Azure::Core::Http::_internal::HttpSanitizer m_httpSanitizer;
580 
581  public:
586  explicit LogPolicy(LogOptions options)
587  : m_options(std::move(options)),
588  m_httpSanitizer(m_options.AllowedHttpQueryParameters, m_options.AllowedHttpHeaders)
589  {
590  }
591 
592  std::unique_ptr<HttpPolicy> Clone() const override
593  {
594  return std::make_unique<LogPolicy>(*this);
595  }
596 
597  std::unique_ptr<RawResponse> Send(
598  Request& request,
599  NextHttpPolicy nextPolicy,
600  Context const& context) const override;
601  };
602  } // namespace _internal
603 }}}} // namespace Azure::Core::Http::Policies
A map<string, string> with case-insensitive key comparison.
A context is a node within a tree that represents deadlines and key/value pairs.
Definition: context.hpp:45
HTTP policy base class.
Definition: policy.hpp:218
HttpPolicy & operator=(const HttpPolicy &other)=default
Assigns this HttpPolicy to copy the other.
virtual ~HttpPolicy()
Destructs HttpPolicy.
Definition: policy.hpp:243
HttpPolicy()=default
Constructs a default instance of HttpPolicy.
virtual std::unique_ptr< RawResponse > Send(Request &request, NextHttpPolicy nextPolicy, Context const &context) const =0
Applies this HTTP policy.
virtual std::unique_ptr< HttpPolicy > Clone() const =0
Creates a clone of this HttpPolicy.
HttpPolicy(HttpPolicy &&other)=default
Contructs HttpPolicy by moving other HttpPolicy.
HttpPolicy(const HttpPolicy &other)=default
Constructs a copy of other HttpPolicy.
The next HTTP policy in the stack sequence of policies.
Definition: policy.hpp:290
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:303
std::unique_ptr< RawResponse > Send(Request &request, Context const &context)
Applies this HTTP policy.
Definition: policy.cpp:13
A request message from a client to a server.
Definition: http.hpp:176
std::string ToString()
Gets Uuid as a string.
Definition: uuid.cpp:20
static Uuid CreateUuid()
Creates a new random UUID.
Definition: uuid.cpp:50
Context for canceling long running operations.
Credentials used for authentication with many (not all) Azure SDK client libraries.
DLL export macro.
#define AZ_CORE_DLLEXPORT
Applies DLL export attribute, when applicable.
Definition: dll_import_export.hpp:93
HTTP request and response functionality.
@ BadGateway
HTTP 502 Bad Gateway.
@ ServiceUnavailable
HTTP 503 Unavailable.
@ RequestTimeout
HTTP 408 Request Timeout.
@ GatewayTimeout
HTTP 504 Gateway Timeout.
@ InternalServerError
HTTP 500 Internal Server Error.
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 SDK abstractions.
Definition: azure_assert.hpp:55
std::shared_ptr< Azure::Core::Http::HttpTransport > AzureSdkGetCustomHttpTransport()
Log options that parameterize the information being logged.
Definition: policy.hpp:120
std::set< std::string > AllowedHttpQueryParameters
HTTP query parameter names that are allowed to be logged.
Definition: policy.hpp:125
CaseInsensitiveSet AllowedHttpHeaders
HTTP header names that are allowed to be logged.
Definition: policy.hpp:131
The set of options that can be specified to influence how retry attempts are made,...
Definition: policy.hpp:80
std::chrono::milliseconds RetryDelay
The minimum permissible delay between retry attempts.
Definition: policy.hpp:92
int32_t MaxRetries
The maximum number of retry attempts before giving up.
Definition: policy.hpp:85
std::chrono::milliseconds MaxRetryDelay
The maximum permissible delay between retry attempts.
Definition: policy.hpp:99
std::set< HttpStatusCode > StatusCodes
The HTTP status codes that indicate when an operation should be retried.
Definition: policy.hpp:105
Telemetry options, used to configure telemetry parameters.
Definition: policy.hpp:56
std::string ApplicationId
The Application ID is the last part of the user agent for telemetry.
Definition: policy.hpp:64
std::shared_ptr< Azure::Core::Tracing::TracerProvider > TracingProvider
Specifies the default distributed tracing provider to use for this client. By default,...
Definition: policy.hpp:70
HTTP transport options parameterize the HTTP transport adapter being used.
Definition: policy.hpp:138
std::shared_ptr< HttpTransport > Transport
Azure::Core::Http::HttpTransport that the transport policy will use to send and receive requests and ...
Definition: policy.hpp:207
Azure::Nullable< std::string > ProxyPassword
The password to use when authenticating with the proxy server.
Definition: policy.hpp:164
bool EnableCertificateRevocationListCheck
Enable TLS Certificate validation against a certificate revocation list.
Definition: policy.hpp:174
std::string ExpectedTlsRootCertificate
Base64 encoded DER representation of an X.509 certificate expected in the certificate chain used in T...
Definition: policy.hpp:187
Azure::Nullable< std::string > HttpProxy
The URL for the proxy server to use for this connection.
Definition: policy.hpp:148
Azure::Nullable< std::string > ProxyUserName
The username to use when authenticating with the proxy server.
Definition: policy.hpp:156
Utilities to be used by HTTP transport implementations.
HTTP pipeline is a stack of HTTP policies.
Universally unique identifier.