Line data Source code
1 : #pragma once 2 : 3 : #include <memory> 4 : 5 : #include "envoy/config/config_provider.h" 6 : #include "envoy/router/router.h" 7 : 8 : namespace Envoy { 9 : namespace Router { 10 : 11 : /** 12 : * Scope key fragment base class. 13 : */ 14 : class ScopeKeyFragmentBase { 15 : public: 16 0 : bool operator!=(const ScopeKeyFragmentBase& other) const { return !(*this == other); } 17 : 18 0 : bool operator==(const ScopeKeyFragmentBase& other) const { 19 0 : if (typeid(*this) == typeid(other)) { 20 0 : return hash() == other.hash(); 21 0 : } 22 0 : return false; 23 0 : } 24 0 : virtual ~ScopeKeyFragmentBase() = default; 25 : 26 : // Hash of the fragment. 27 : virtual uint64_t hash() const PURE; 28 : }; 29 : 30 : /** 31 : * Scope Key is composed of non-null fragments. 32 : **/ 33 : class ScopeKey { 34 : public: 35 0 : ScopeKey() = default; 36 0 : ScopeKey(ScopeKey&& other) = default; 37 : 38 : // Scopekey is not copy-assignable and copy-constructible as it contains unique_ptr inside itself. 39 : ScopeKey(const ScopeKey&) = delete; 40 : ScopeKey operator=(const ScopeKey&) = delete; 41 : 42 : // Caller should guarantee the fragment is not nullptr. 43 0 : void addFragment(std::unique_ptr<ScopeKeyFragmentBase>&& fragment) { 44 0 : ASSERT(fragment != nullptr, "null fragment not allowed in ScopeKey."); 45 0 : updateHash(*fragment); 46 0 : fragments_.emplace_back(std::move(fragment)); 47 0 : } 48 : 49 0 : uint64_t hash() const { return hash_; } 50 : bool operator!=(const ScopeKey& other) const; 51 : bool operator==(const ScopeKey& other) const; 52 : 53 : private: 54 : // Update the key's hash with the new fragment hash. 55 0 : void updateHash(const ScopeKeyFragmentBase& fragment) { 56 0 : std::stringbuf buffer; 57 0 : buffer.sputn(reinterpret_cast<const char*>(&hash_), sizeof(hash_)); 58 0 : const auto& fragment_hash = fragment.hash(); 59 0 : buffer.sputn(reinterpret_cast<const char*>(&fragment_hash), sizeof(fragment_hash)); 60 0 : hash_ = HashUtil::xxHash64(buffer.str()); 61 0 : } 62 : 63 : uint64_t hash_{0}; 64 : std::vector<std::unique_ptr<ScopeKeyFragmentBase>> fragments_; 65 : }; 66 : 67 : using ScopeKeyPtr = std::unique_ptr<ScopeKey>; 68 : 69 : // String fragment. 70 : class StringKeyFragment : public ScopeKeyFragmentBase { 71 : public: 72 : explicit StringKeyFragment(absl::string_view value) 73 0 : : value_(value), hash_(HashUtil::xxHash64(value_)) {} 74 : 75 0 : uint64_t hash() const override { return hash_; } 76 : 77 : private: 78 : const std::string value_; 79 : const uint64_t hash_; 80 : }; 81 : 82 : /** 83 : * The scoped key builder. 84 : */ 85 : class ScopeKeyBuilder { 86 : public: 87 170 : virtual ~ScopeKeyBuilder() = default; 88 : 89 : /** 90 : * Based on the incoming HTTP request headers, returns the hash value of its scope key. 91 : * @param headers the request headers to match the scoped routing configuration against. 92 : * @return unique_ptr of the scope key computed from header. 93 : */ 94 : virtual ScopeKeyPtr computeScopeKey(const Http::HeaderMap&) const PURE; 95 : }; 96 : 97 : /** 98 : * The scoped routing configuration. 99 : */ 100 : class ScopedConfig : public Envoy::Config::ConfigProvider::Config { 101 : public: 102 170 : ~ScopedConfig() override = default; 103 : 104 : /** 105 : * Based on the scope key, returns the configuration to use for selecting a target route. 106 : * The scope key can be got via ScopeKeyBuilder. 107 : * 108 : * @param scope_key the scope key. null config will be returned when null. 109 : * @return ConfigConstSharedPtr the router's Config matching the request headers. 110 : */ 111 : virtual ConfigConstSharedPtr getRouteConfig(const ScopeKeyPtr& scope_key) const PURE; 112 : }; 113 : 114 : using ScopedConfigConstSharedPtr = std::shared_ptr<const ScopedConfig>; 115 : using ScopeKeyBuilderPtr = std::unique_ptr<const ScopeKeyBuilder>; 116 : 117 : } // namespace Router 118 : } // namespace Envoy