azure-core
Loading...
Searching...
No Matches
policy.hpp
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
9#pragma once
10
14#include "azure/core/dll_import_export.hpp"
17#include "azure/core/internal/http/http_sanitizer.hpp"
18#include "azure/core/uuid.hpp"
19
20#include <atomic>
21#include <chrono>
22#include <cstddef>
23#include <map>
24#include <memory>
25#include <mutex>
26#include <set>
27#include <shared_mutex>
28#include <string>
29#include <utility>
30#include <vector>
31
39extern std::shared_ptr<Azure::Core::Http::HttpTransport> AzureSdkGetCustomHttpTransport();
40
41namespace 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
51 namespace _internal {
52 class TelemetryPolicy;
53 }
54
59 struct TelemetryOptions final
60 {
68 std::string ApplicationId;
69
74 std::shared_ptr<Azure::Core::Tracing::TracerProvider> TracingProvider;
75
76 private:
77 // The friend declaration is needed so that TelemetryPolicy could access CppStandardVersion,
78 // and it is not a struct's public field like the ones above to be set non-programmatically.
79 // When building the SDK, tests, or samples, the value of __cplusplus is ultimately controlled
80 // by the cmake files in this repo (i.e. C++14), therefore we set distinct values of 0, -1, etc
81 // when it is the case.
82 friend class _internal::TelemetryPolicy;
83 long CppStandardVersion =
84#if defined(_azure_BUILDING_SDK)
85 -2L
86#elif defined(_azure_BUILDING_TESTS)
87 -1L
88#elif defined(_azure_BUILDING_SAMPLES)
89 0L
90#else
91 // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
92#if defined(_MSVC_LANG) && __cplusplus == 199711L
93 _MSVC_LANG
94#else
95 __cplusplus
96#endif
97#endif
98 ;
99 };
100
107 struct RetryOptions final
108 {
113 int32_t MaxRetries = 3;
114
120 std::chrono::milliseconds RetryDelay = std::chrono::milliseconds(800);
121
127 std::chrono::milliseconds MaxRetryDelay = std::chrono::seconds(60);
128
133 std::set<HttpStatusCode> StatusCodes{
134 HttpStatusCode::RequestTimeout,
135 HttpStatusCode::InternalServerError,
136 HttpStatusCode::BadGateway,
137 HttpStatusCode::ServiceUnavailable,
138 HttpStatusCode::GatewayTimeout,
139 };
140 };
141
147 struct LogOptions final
148 {
153 std::set<std::string> AllowedHttpQueryParameters = _detail::g_defaultAllowedHttpQueryParameters;
154
159 CaseInsensitiveSet AllowedHttpHeaders = _detail::g_defaultAllowedHttpHeaders;
160 };
161
165 struct TransportOptions final
166 {
177
185
193
203
216
229
248 std::shared_ptr<HttpTransport> Transport;
249 };
250
251 class NextHttpPolicy;
252
260 public:
261 // If we get a response that goes up the stack
262 // Any errors in the pipeline throws an exception
263 // At the top of the pipeline we might want to turn certain responses into exceptions
264
275 virtual std::unique_ptr<RawResponse> Send(
276 Request& request,
277 NextHttpPolicy nextPolicy,
278 Context const& context) const = 0;
279
284 virtual ~HttpPolicy() {}
285
290 virtual std::unique_ptr<HttpPolicy> Clone() const = 0;
291
292 protected:
297 HttpPolicy() = default;
298
304 HttpPolicy(const HttpPolicy& other) = default;
305
312 HttpPolicy& operator=(const HttpPolicy& other) = default;
313
319 HttpPolicy(HttpPolicy&& other) = default;
320 };
321
331 class NextHttpPolicy final {
332 const size_t m_index;
333 const std::vector<std::unique_ptr<HttpPolicy>>& m_policies;
334
335 public:
344 explicit NextHttpPolicy(size_t index, const std::vector<std::unique_ptr<HttpPolicy>>& policies)
345 : m_index(index), m_policies(policies)
346 {
347 }
348
358 std::unique_ptr<RawResponse> Send(Request& request, Context const& context);
359 };
360
361 namespace _internal {
362
367 class TransportPolicy final : public HttpPolicy {
368 private:
369 TransportOptions m_options;
370
371 public:
377 explicit TransportPolicy(TransportOptions const& options = TransportOptions());
378
379 std::unique_ptr<HttpPolicy> Clone() const override
380 {
381 return std::make_unique<TransportPolicy>(*this);
382 }
383
384 std::unique_ptr<RawResponse> Send(
385 Request& request,
386 NextHttpPolicy nextPolicy,
387 Context const& context) const override;
388 };
389
399 class RetryPolicyBase : public HttpPolicy {
400 private:
401 RetryOptions m_retryOptions;
402
403 public:
410 explicit RetryPolicyBase(RetryOptions options) : m_retryOptions(std::move(options)) {}
411
412 std::unique_ptr<RawResponse> Send(
413 Request& request,
414 NextHttpPolicy nextPolicy,
415 Context const& context) const final;
416
428 static int32_t GetRetryCount(Context const& context);
429
430 protected:
431 virtual bool ShouldRetryOnTransportFailure(
432 RetryOptions const& retryOptions,
433 int32_t attempt,
434 std::chrono::milliseconds& retryAfter,
435 double jitterFactor = -1) const;
436
437 virtual bool ShouldRetryOnResponse(
438 RawResponse const& response,
439 RetryOptions const& retryOptions,
440 int32_t attempt,
441 std::chrono::milliseconds& retryAfter,
442 double jitterFactor = -1) const;
443 };
444
448 class RetryPolicy final : public RetryPolicyBase {
449 public:
455 explicit RetryPolicy(RetryOptions options) : RetryPolicyBase(std::move(options)) {}
456
457 std::unique_ptr<HttpPolicy> Clone() const override
458 {
459 return std::make_unique<RetryPolicy>(*this);
460 }
461 };
462
469 class RequestIdPolicy final : public HttpPolicy {
470 private:
471 constexpr static const char* RequestIdHeader = "x-ms-client-request-id";
472
473 public:
478 explicit RequestIdPolicy() {}
479
480 std::unique_ptr<HttpPolicy> Clone() const override
481 {
482 return std::make_unique<RequestIdPolicy>(*this);
483 }
484
485 std::unique_ptr<RawResponse> Send(
486 Request& request,
487 NextHttpPolicy nextPolicy,
488 Context const& context) const override
489 {
490 if (!request.GetHeader(RequestIdHeader).HasValue())
491 {
492 auto const uuid = Uuid::CreateUuid().ToString();
493 request.SetHeader(RequestIdHeader, uuid);
494 }
495
496 return nextPolicy.Send(request, context);
497 }
498 };
499
508 class RequestActivityPolicy final : public HttpPolicy {
509 private:
510 Azure::Core::Http::_internal::HttpSanitizer m_httpSanitizer;
511
512 public:
516 // explicit RequestActivityPolicy() = default;
522 explicit RequestActivityPolicy(
523 Azure::Core::Http::_internal::HttpSanitizer const& httpSanitizer)
524 : m_httpSanitizer(httpSanitizer)
525 {
526 }
527
528 std::unique_ptr<HttpPolicy> Clone() const override
529 {
530 return std::make_unique<RequestActivityPolicy>(*this);
531 }
532
533 std::unique_ptr<RawResponse> Send(
534 Request& request,
535 NextHttpPolicy nextPolicy,
536 Context const& context) const override;
537 };
538
552 class TelemetryPolicy final : public HttpPolicy {
553 private:
554 std::string const m_telemetryId;
555
556 public:
564 explicit TelemetryPolicy(
565 std::string const& packageName,
566 std::string const& packageVersion,
567 TelemetryOptions options = TelemetryOptions())
568 : m_telemetryId(Azure::Core::Http::_internal::HttpShared::GenerateUserAgent(
569 packageName,
570 packageVersion,
571 options.ApplicationId,
572 options.CppStandardVersion))
573 {
574 }
575
576 std::unique_ptr<HttpPolicy> Clone() const override
577 {
578 return std::make_unique<TelemetryPolicy>(*this);
579 }
580
581 std::unique_ptr<RawResponse> Send(
582 Request& request,
583 NextHttpPolicy nextPolicy,
584 Context const& context) const override;
585 };
586
591 class BearerTokenAuthenticationPolicy : public HttpPolicy {
592 private:
593 std::shared_ptr<const Credentials::TokenCredential> m_credential;
594 Credentials::TokenRequestContext m_tokenRequestContext;
595
596 mutable Credentials::AccessToken m_accessToken;
597 mutable std::shared_timed_mutex m_accessTokenMutex;
598 mutable Credentials::TokenRequestContext m_accessTokenContext;
599 mutable std::atomic<bool> m_invalidateToken = {false};
600
601 public:
608 explicit BearerTokenAuthenticationPolicy(
609 std::shared_ptr<const Credentials::TokenCredential> credential,
610 Credentials::TokenRequestContext tokenRequestContext)
611 : m_credential(std::move(credential)),
612 m_tokenRequestContext(std::move(tokenRequestContext))
613 {
614 }
615
616 std::unique_ptr<HttpPolicy> Clone() const override
617 {
618 // Can't use std::make_shared here because copy constructor is not public.
619 return std::unique_ptr<HttpPolicy>(new BearerTokenAuthenticationPolicy(*this));
620 }
621
622 std::unique_ptr<RawResponse> Send(
623 Request& request,
624 NextHttpPolicy nextPolicy,
625 Context const& context) const override;
626
627 protected:
628 BearerTokenAuthenticationPolicy(BearerTokenAuthenticationPolicy const& other)
629 : BearerTokenAuthenticationPolicy(other.m_credential, other.m_tokenRequestContext)
630 {
631 std::shared_lock<std::shared_timed_mutex> readLock(other.m_accessTokenMutex);
632 m_accessToken = other.m_accessToken;
633 m_accessTokenContext = other.m_accessTokenContext;
634 m_invalidateToken.store(other.m_invalidateToken.load());
635 }
636
637 void operator=(BearerTokenAuthenticationPolicy const&) = delete;
638
639 virtual std::unique_ptr<RawResponse> AuthorizeAndSendRequest(
640 Request& request,
641 NextHttpPolicy& nextPolicy,
642 Context const& context) const;
643
644 virtual bool AuthorizeRequestOnChallenge(
645 std::string const& challenge,
646 Request& request,
647 Context const& context) const;
648
649 void AuthenticateAndAuthorizeRequest(
650 Request& request,
651 Credentials::TokenRequestContext const& tokenRequestContext,
652 Context const& context) const;
653 };
654
661 class LogPolicy final : public HttpPolicy {
662 LogOptions m_options;
663 Azure::Core::Http::_internal::HttpSanitizer m_httpSanitizer;
664
665 public:
670 explicit LogPolicy(LogOptions options)
671 : m_options(std::move(options)),
672 m_httpSanitizer(m_options.AllowedHttpQueryParameters, m_options.AllowedHttpHeaders)
673 {
674 }
675
676 std::unique_ptr<HttpPolicy> Clone() const override
677 {
678 return std::make_unique<LogPolicy>(*this);
679 }
680
681 std::unique_ptr<RawResponse> Send(
682 Request& request,
683 NextHttpPolicy nextPolicy,
684 Context const& context) const override;
685 };
686 } // namespace _internal
687}}}} // namespace Azure::Core::Http::Policies
A map<string, string> with case-insensitive key comparison.
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
A context is a node within a unidirectional tree that represents deadlines and key/value pairs.
Definition context.hpp:72
HTTP policy base class.
Definition policy.hpp:259
virtual ~HttpPolicy()
Destructs HttpPolicy.
Definition policy.hpp:284
HttpPolicy()=default
Constructs a default instance of HttpPolicy.
HttpPolicy & operator=(const HttpPolicy &other)=default
Assigns this HttpPolicy to copy the other.
virtual std::unique_ptr< HttpPolicy > Clone() const =0
Creates a clone of this HttpPolicy.
HttpPolicy(HttpPolicy &&other)=default
Constructs HttpPolicy by moving other HttpPolicy.
HttpPolicy(const HttpPolicy &other)=default
Constructs a copy of other HttpPolicy.
virtual std::unique_ptr< RawResponse > Send(Request &request, NextHttpPolicy nextPolicy, Context const &context) const =0
Applies this HTTP policy.
The next HTTP policy in the stack sequence of policies.
Definition policy.hpp:331
std::unique_ptr< RawResponse > Send(Request &request, Context const &context)
Applies this HTTP policy.
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:344
A request message from a client to a server.
Definition http.hpp:183
std::string ToString() const
Gets Uuid as a string.
static Uuid CreateUuid()
Creates a new random UUID.
Manages an optional contained value, i.e. a value that may or may not be present.
Definition nullable.hpp:30
Context for canceling long running operations.
Credentials used for authentication with many (not all) Azure SDK client libraries.
HTTP request and response functionality.
Compute the hash value for the input binary data, using SHA256, SHA384 and SHA512.
Definition azure_assert.hpp:57
std::shared_ptr< Azure::Core::Http::HttpTransport > AzureSdkGetCustomHttpTransport()
Log options that parameterize the information being logged.
Definition policy.hpp:148
std::set< std::string > AllowedHttpQueryParameters
HTTP query parameter names that are allowed to be logged.
Definition policy.hpp:153
CaseInsensitiveSet AllowedHttpHeaders
HTTP header names that are allowed to be logged.
Definition policy.hpp:159
The set of options that can be specified to influence how retry attempts are made,...
Definition policy.hpp:108
std::chrono::milliseconds RetryDelay
The minimum permissible delay between retry attempts.
Definition policy.hpp:120
int32_t MaxRetries
The maximum number of retry attempts before giving up.
Definition policy.hpp:113
std::chrono::milliseconds MaxRetryDelay
The maximum permissible delay between retry attempts.
Definition policy.hpp:127
std::set< HttpStatusCode > StatusCodes
The HTTP status codes that indicate when an operation should be retried.
Definition policy.hpp:133
Telemetry options, used to configure telemetry parameters.
Definition policy.hpp:60
std::string ApplicationId
The Application ID is the last part of the user agent for telemetry.
Definition policy.hpp:68
std::shared_ptr< Azure::Core::Tracing::TracerProvider > TracingProvider
Specifies the default distributed tracing provider to use for this client. By default,...
Definition policy.hpp:74
HTTP transport options parameterize the HTTP transport adapter being used.
Definition policy.hpp:166
bool DisableTlsCertificateValidation
Disable SSL/TLS certificate verification. This option allows transport layer to perform insecure SSL/...
Definition policy.hpp:215
std::shared_ptr< HttpTransport > Transport
Azure::Core::Http::HttpTransport that the transport policy will use to send and receive requests and ...
Definition policy.hpp:248
Azure::Nullable< std::string > ProxyPassword
The password to use when authenticating with the proxy server.
Definition policy.hpp:192
bool EnableCertificateRevocationListCheck
Enable TLS Certificate validation against a certificate revocation list.
Definition policy.hpp:202
std::string ExpectedTlsRootCertificate
Base64 encoded DER representation of an X.509 certificate expected in the certificate chain used in T...
Definition policy.hpp:228
Azure::Nullable< std::string > HttpProxy
The URL for the proxy server to use for this connection.
Definition policy.hpp:176
Azure::Nullable< std::string > ProxyUserName
The username to use when authenticating with the proxy server.
Definition policy.hpp:184
Utilities to be used by HTTP transport implementations.
Universally unique identifier.