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"
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 <shared_mutex>
29#include <string>
30#include <utility>
31#include <vector>
32
40extern std::shared_ptr<Azure::Core::Http::HttpTransport> AzureSdkGetCustomHttpTransport();
41
42namespace Azure { namespace Core { namespace Http { namespace Policies {
43
44 struct TransportOptions;
45 namespace _detail {
46 std::shared_ptr<HttpTransport> GetTransportAdapter(TransportOptions const& transportOptions);
47
48 AZ_CORE_DLLEXPORT extern std::set<std::string> const g_defaultAllowedHttpQueryParameters;
49 AZ_CORE_DLLEXPORT extern CaseInsensitiveSet const g_defaultAllowedHttpHeaders;
50 } // namespace _detail
51
52 namespace _internal {
53 class TelemetryPolicy;
54 }
55
60 struct TelemetryOptions final
61 {
69 std::string ApplicationId;
70
75 std::shared_ptr<Azure::Core::Tracing::TracerProvider> TracingProvider;
76
77 private:
78 // The friend declaration is needed so that TelemetryPolicy could access CppStandardVersion,
79 // and it is not a struct's public field like the ones above to be set non-programmatically.
80 // When building the SDK, tests, or samples, the value of __cplusplus is ultimately controlled
81 // by the cmake files in this repo (i.e. C++14), therefore we set distinct values of 0, -1, etc
82 // when it is the case.
83 friend class _internal::TelemetryPolicy;
84 long CppStandardVersion =
85#if defined(_azure_BUILDING_SDK)
86 -2L
87#elif defined(_azure_BUILDING_TESTS)
88 -1L
89#elif defined(_azure_BUILDING_SAMPLES)
90 0L
91#else
92 __cplusplus
93#endif
94 ;
95 };
96
103 struct RetryOptions final
104 {
109 int32_t MaxRetries = 3;
110
116 std::chrono::milliseconds RetryDelay = std::chrono::milliseconds(800);
117
123 std::chrono::milliseconds MaxRetryDelay = std::chrono::seconds(60);
124
129 std::set<HttpStatusCode> StatusCodes{
130 HttpStatusCode::RequestTimeout,
131 HttpStatusCode::InternalServerError,
132 HttpStatusCode::BadGateway,
133 HttpStatusCode::ServiceUnavailable,
134 HttpStatusCode::GatewayTimeout,
135 };
136 };
137
143 struct LogOptions final
144 {
149 std::set<std::string> AllowedHttpQueryParameters = _detail::g_defaultAllowedHttpQueryParameters;
150
155 CaseInsensitiveSet AllowedHttpHeaders = _detail::g_defaultAllowedHttpHeaders;
156 };
157
161 struct TransportOptions final
162 {
173
181
189
199
212
225
244 std::shared_ptr<HttpTransport> Transport;
245 };
246
247 class NextHttpPolicy;
248
256 public:
257 // If we get a response that goes up the stack
258 // Any errors in the pipeline throws an exception
259 // At the top of the pipeline we might want to turn certain responses into exceptions
260
271 virtual std::unique_ptr<RawResponse> Send(
272 Request& request,
273 NextHttpPolicy nextPolicy,
274 Context const& context) const = 0;
275
280 virtual ~HttpPolicy() {}
281
286 virtual std::unique_ptr<HttpPolicy> Clone() const = 0;
287
288 protected:
293 HttpPolicy() = default;
294
300 HttpPolicy(const HttpPolicy& other) = default;
301
308 HttpPolicy& operator=(const HttpPolicy& other) = default;
309
315 HttpPolicy(HttpPolicy&& other) = default;
316 };
317
327 class NextHttpPolicy final {
328 const size_t m_index;
329 const std::vector<std::unique_ptr<HttpPolicy>>& m_policies;
330
331 public:
340 explicit NextHttpPolicy(size_t index, const std::vector<std::unique_ptr<HttpPolicy>>& policies)
341 : m_index(index), m_policies(policies)
342 {
343 }
344
354 std::unique_ptr<RawResponse> Send(Request& request, Context const& context);
355 };
356
357 namespace _internal {
358
363 class TransportPolicy final : public HttpPolicy {
364 private:
365 TransportOptions m_options;
366
367 public:
373 explicit TransportPolicy(TransportOptions const& options = TransportOptions());
374
375 std::unique_ptr<HttpPolicy> Clone() const override
376 {
377 return std::make_unique<TransportPolicy>(*this);
378 }
379
380 std::unique_ptr<RawResponse> Send(
381 Request& request,
382 NextHttpPolicy nextPolicy,
383 Context const& context) const override;
384 };
385
389 class RetryPolicy
390#if !defined(_azure_TESTING_BUILD)
391 final
392#endif
393 : public HttpPolicy {
394 private:
395 RetryOptions m_retryOptions;
396
397 public:
403 explicit RetryPolicy(RetryOptions options) : m_retryOptions(std::move(options)) {}
404
405 std::unique_ptr<HttpPolicy> Clone() const override
406 {
407 return std::make_unique<RetryPolicy>(*this);
408 }
409
410 std::unique_ptr<RawResponse> Send(
411 Request& request,
412 NextHttpPolicy nextPolicy,
413 Context const& context) const final;
414
426 static int32_t GetRetryCount(Context const& context);
427
428 protected:
429 virtual bool ShouldRetryOnTransportFailure(
430 RetryOptions const& retryOptions,
431 int32_t attempt,
432 std::chrono::milliseconds& retryAfter,
433 double jitterFactor = -1) const;
434
435 virtual bool ShouldRetryOnResponse(
436 RawResponse const& response,
437 RetryOptions const& retryOptions,
438 int32_t attempt,
439 std::chrono::milliseconds& retryAfter,
440 double jitterFactor = -1) const;
441 };
442
449 class RequestIdPolicy final : public HttpPolicy {
450 private:
451 constexpr static const char* RequestIdHeader = "x-ms-client-request-id";
452
453 public:
458 explicit RequestIdPolicy() {}
459
460 std::unique_ptr<HttpPolicy> Clone() const override
461 {
462 return std::make_unique<RequestIdPolicy>(*this);
463 }
464
465 std::unique_ptr<RawResponse> Send(
466 Request& request,
467 NextHttpPolicy nextPolicy,
468 Context const& context) const override
469 {
470 if (!request.GetHeader(RequestIdHeader).HasValue())
471 {
472 auto const uuid = Uuid::CreateUuid().ToString();
473 request.SetHeader(RequestIdHeader, uuid);
474 }
475
476 return nextPolicy.Send(request, context);
477 }
478 };
479
488 class RequestActivityPolicy final : public HttpPolicy {
489 private:
490 Azure::Core::Http::_internal::HttpSanitizer m_httpSanitizer;
491
492 public:
496 // explicit RequestActivityPolicy() = default;
502 explicit RequestActivityPolicy(
503 Azure::Core::Http::_internal::HttpSanitizer const& httpSanitizer)
504 : m_httpSanitizer(httpSanitizer)
505 {
506 }
507
508 std::unique_ptr<HttpPolicy> Clone() const override
509 {
510 return std::make_unique<RequestActivityPolicy>(*this);
511 }
512
513 std::unique_ptr<RawResponse> Send(
514 Request& request,
515 NextHttpPolicy nextPolicy,
516 Context const& context) const override;
517 };
518
532 class TelemetryPolicy final : public HttpPolicy {
533 private:
534 std::string const m_telemetryId;
535
536 public:
544 explicit TelemetryPolicy(
545 std::string const& packageName,
546 std::string const& packageVersion,
547 TelemetryOptions options = TelemetryOptions())
548 : m_telemetryId(Azure::Core::Http::_detail::UserAgentGenerator::GenerateUserAgent(
549 packageName,
550 packageVersion,
551 options.ApplicationId,
552 options.CppStandardVersion))
553 {
554 }
555
556 std::unique_ptr<HttpPolicy> Clone() const override
557 {
558 return std::make_unique<TelemetryPolicy>(*this);
559 }
560
561 std::unique_ptr<RawResponse> Send(
562 Request& request,
563 NextHttpPolicy nextPolicy,
564 Context const& context) const override;
565 };
566
571 class BearerTokenAuthenticationPolicy : public HttpPolicy {
572 private:
573 std::shared_ptr<Credentials::TokenCredential const> const m_credential;
574 Credentials::TokenRequestContext m_tokenRequestContext;
575
576 mutable Credentials::AccessToken m_accessToken;
577 mutable std::shared_timed_mutex m_accessTokenMutex;
578 mutable Credentials::TokenRequestContext m_accessTokenContext;
579
580 public:
587 explicit BearerTokenAuthenticationPolicy(
588 std::shared_ptr<Credentials::TokenCredential const> credential,
589 Credentials::TokenRequestContext tokenRequestContext)
590 : m_credential(std::move(credential)),
591 m_tokenRequestContext(std::move(tokenRequestContext))
592 {
593 }
594
595 std::unique_ptr<HttpPolicy> Clone() const override
596 {
597 // Can't use std::make_shared here because copy constructor is not public.
598 return std::unique_ptr<HttpPolicy>(new BearerTokenAuthenticationPolicy(*this));
599 }
600
601 std::unique_ptr<RawResponse> Send(
602 Request& request,
603 NextHttpPolicy nextPolicy,
604 Context const& context) const override;
605
606 protected:
607 BearerTokenAuthenticationPolicy(BearerTokenAuthenticationPolicy const& other)
608 : BearerTokenAuthenticationPolicy(other.m_credential, other.m_tokenRequestContext)
609 {
610 std::shared_lock<std::shared_timed_mutex> readLock(other.m_accessTokenMutex);
611 m_accessToken = other.m_accessToken;
612 m_accessTokenContext = other.m_accessTokenContext;
613 }
614
615 void operator=(BearerTokenAuthenticationPolicy const&) = delete;
616
617 virtual std::unique_ptr<RawResponse> AuthorizeAndSendRequest(
618 Request& request,
619 NextHttpPolicy& nextPolicy,
620 Context const& context) const;
621
622 virtual bool AuthorizeRequestOnChallenge(
623 std::string const& challenge,
624 Request& request,
625 Context const& context) const;
626
627 void AuthenticateAndAuthorizeRequest(
628 Request& request,
629 Credentials::TokenRequestContext const& tokenRequestContext,
630 Context const& context) const;
631 };
632
639 class LogPolicy final : public HttpPolicy {
640 LogOptions m_options;
641 Azure::Core::Http::_internal::HttpSanitizer m_httpSanitizer;
642
643 public:
648 explicit LogPolicy(LogOptions options)
649 : m_options(std::move(options)),
650 m_httpSanitizer(m_options.AllowedHttpQueryParameters, m_options.AllowedHttpHeaders)
651 {
652 }
653
654 std::unique_ptr<HttpPolicy> Clone() const override
655 {
656 return std::make_unique<LogPolicy>(*this);
657 }
658
659 std::unique_ptr<RawResponse> Send(
660 Request& request,
661 NextHttpPolicy nextPolicy,
662 Context const& context) const override;
663 };
664 } // namespace _internal
665}}}} // 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:255
virtual ~HttpPolicy()
Destructs HttpPolicy.
Definition policy.hpp:280
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:327
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:340
std::unique_ptr< RawResponse > Send(Request &request, Context const &context)
Applies this HTTP policy.
Definition policy.cpp:14
A request message from a client to a server.
Definition http.hpp:182
std::string ToString() const
Gets Uuid as a string.
Definition uuid.cpp:66
static Uuid CreateUuid()
Creates a new random UUID.
Definition uuid.cpp:134
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:144
std::set< std::string > AllowedHttpQueryParameters
HTTP query parameter names that are allowed to be logged.
Definition policy.hpp:149
CaseInsensitiveSet AllowedHttpHeaders
HTTP header names that are allowed to be logged.
Definition policy.hpp:155
The set of options that can be specified to influence how retry attempts are made,...
Definition policy.hpp:104
std::chrono::milliseconds RetryDelay
The minimum permissible delay between retry attempts.
Definition policy.hpp:116
int32_t MaxRetries
The maximum number of retry attempts before giving up.
Definition policy.hpp:109
std::chrono::milliseconds MaxRetryDelay
The maximum permissible delay between retry attempts.
Definition policy.hpp:123
std::set< HttpStatusCode > StatusCodes
The HTTP status codes that indicate when an operation should be retried.
Definition policy.hpp:129
Telemetry options, used to configure telemetry parameters.
Definition policy.hpp:61
std::string ApplicationId
The Application ID is the last part of the user agent for telemetry.
Definition policy.hpp:69
std::shared_ptr< Azure::Core::Tracing::TracerProvider > TracingProvider
Specifies the default distributed tracing provider to use for this client. By default,...
Definition policy.hpp:75
HTTP transport options parameterize the HTTP transport adapter being used.
Definition policy.hpp:162
bool DisableTlsCertificateValidation
Disable SSL/TLS certificate verification. This option allows transport layer to perform insecure SSL/...
Definition policy.hpp:211
std::shared_ptr< HttpTransport > Transport
Azure::Core::Http::HttpTransport that the transport policy will use to send and receive requests and ...
Definition policy.hpp:244
Azure::Nullable< std::string > ProxyPassword
The password to use when authenticating with the proxy server.
Definition policy.hpp:188
bool EnableCertificateRevocationListCheck
Enable TLS Certificate validation against a certificate revocation list.
Definition policy.hpp:198
std::string ExpectedTlsRootCertificate
Base64 encoded DER representation of an X.509 certificate expected in the certificate chain used in T...
Definition policy.hpp:224
Azure::Nullable< std::string > HttpProxy
The URL for the proxy server to use for this connection.
Definition policy.hpp:172
Azure::Nullable< std::string > ProxyUserName
The username to use when authenticating with the proxy server.
Definition policy.hpp:180
Utilities to be used by HTTP transport implementations.
Declaration of the UserAgentGenerator type.
Universally unique identifier.