From aeb386f28685207e3aab2c9cf2ce83aad2bf02f3 Mon Sep 17 00:00:00 2001 From: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com> Date: Wed, 27 Jan 2021 10:51:53 -0800 Subject: [PATCH] Add ValuePolicy (#1458) --- .../azure-core/inc/azure/core/http/policy.hpp | 60 +++++++++++++++++++ sdk/core/azure-core/test/ut/policy.cpp | 43 +++++++++++++ 2 files changed, 103 insertions(+) diff --git a/sdk/core/azure-core/inc/azure/core/http/policy.hpp b/sdk/core/azure-core/inc/azure/core/http/policy.hpp index 8883e60a5..cdb366b66 100644 --- a/sdk/core/azure-core/inc/azure/core/http/policy.hpp +++ b/sdk/core/azure-core/inc/azure/core/http/policy.hpp @@ -16,7 +16,13 @@ #include "azure/core/uuid.hpp" #include +#include +#include +#include +#include +#include #include +#include namespace Azure { namespace Core { namespace Http { @@ -415,4 +421,58 @@ namespace Azure { namespace Core { namespace Http { static constexpr auto const HttpTransportAdapter = Classification(4); }; + namespace Details { + /** + * @brief @ValuePolicy options. + */ + struct ValuePolicyOptions + { + std::map HeaderValues; + std::map QueryValues; + }; + + /** + * @brief Value policy. + * + * @details Applies key-value pair values to each HTTP request (either HTTP headers or query + * parameters). + */ + class ValuePolicy : public HttpPolicy { + private: + ValuePolicyOptions m_options; + + public: + /** + * @brief Construct a @ValuePolicy with the @ValuePolicyOptions provided. + * @param options @ValuePolicyOptions. + */ + explicit ValuePolicy(ValuePolicyOptions options) : m_options(std::move(options)) {} + + std::unique_ptr Clone() const override + { + return std::make_unique(*this); + } + + std::unique_ptr Send( + Context const& ctx, + Request& request, + NextHttpPolicy nextHttpPolicy) const override + { + for (auto const& hdrPair : m_options.HeaderValues) + { + request.AddHeader(hdrPair.first, hdrPair.second); + } + + { + auto& url = request.GetUrl(); + for (auto const& qryPair : m_options.QueryValues) + { + url.AppendQueryParameter(qryPair.first, qryPair.second); + } + } + + return nextHttpPolicy.Send(ctx, request); + } + }; + } // namespace Details }}} // namespace Azure::Core::Http diff --git a/sdk/core/azure-core/test/ut/policy.cpp b/sdk/core/azure-core/test/ut/policy.cpp index b037da963..cd443a7fe 100644 --- a/sdk/core/azure-core/test/ut/policy.cpp +++ b/sdk/core/azure-core/test/ut/policy.cpp @@ -7,6 +7,24 @@ #include +namespace { +class NoOpPolicy : public Azure::Core::Http::HttpPolicy { +public: + std::unique_ptr Clone() const override + { + return std::make_unique(*this); + } + + std::unique_ptr Send( + Azure::Core::Context const&, + Azure::Core::Http::Request&, + Azure::Core::Http::NextHttpPolicy) const override + { + return nullptr; + } +}; +} // namespace + TEST(Policy, throwWhenNoTransportPolicy) { // Construct pipeline without exception @@ -44,3 +62,28 @@ TEST(Policy, throwWhenNoTransportPolicyMessage) EXPECT_STREQ("Invalid pipeline. No transport policy found. Endless policy.", err.what()); } } + +TEST(Policy, ValuePolicy) +{ + using namespace Azure::Core; + using namespace Azure::Core::Http; + + Azure::Core::Http::Details::ValuePolicyOptions options + = {{{"hdrkey1", "HdrVal1"}, {"hdrkey2", "HdrVal2"}}, + {{"QryKey1", "QryVal1"}, {"QryKey2", "QryVal2"}}}; + + std::vector> policies; + policies.emplace_back(std::make_unique(options)); + policies.emplace_back(std::make_unique()); + HttpPipeline pipeline(policies); + + Request request(HttpMethod::Get, Url("https:://www.example.com")); + + pipeline.Send(GetApplicationContext(), request); + + auto headers = request.GetHeaders(); + auto queryParams = request.GetUrl().GetQueryParameters(); + + ASSERT_EQ(headers, decltype(headers)({{"hdrkey1", "HdrVal1"}, {"hdrkey2", "HdrVal2"}})); + ASSERT_EQ(queryParams, decltype(queryParams)({{"QryKey1", "QryVal1"}, {"QryKey2", "QryVal2"}})); +}