LCOV - code coverage report
Current view: top level - source/common/router - config_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 204 549 37.2 %
Date: 2024-01-05 06:35:25 Functions: 78 251 31.1 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <chrono>
       4             : #include <cstdint>
       5             : #include <iterator>
       6             : #include <list>
       7             : #include <map>
       8             : #include <memory>
       9             : #include <regex>
      10             : #include <string>
      11             : #include <vector>
      12             : 
      13             : #include "envoy/config/core/v3/base.pb.h"
      14             : #include "envoy/config/route/v3/route.pb.h"
      15             : #include "envoy/config/route/v3/route_components.pb.h"
      16             : #include "envoy/config/route/v3/route_components.pb.validate.h"
      17             : #include "envoy/registry/registry.h"
      18             : #include "envoy/router/cluster_specifier_plugin.h"
      19             : #include "envoy/router/router.h"
      20             : #include "envoy/runtime/runtime.h"
      21             : #include "envoy/server/filter_config.h"
      22             : #include "envoy/type/v3/percent.pb.h"
      23             : #include "envoy/upstream/cluster_manager.h"
      24             : 
      25             : #include "source/common/common/matchers.h"
      26             : #include "source/common/common/packed_struct.h"
      27             : #include "source/common/config/metadata.h"
      28             : #include "source/common/http/hash_policy.h"
      29             : #include "source/common/http/header_utility.h"
      30             : #include "source/common/matcher/matcher.h"
      31             : #include "source/common/router/config_utility.h"
      32             : #include "source/common/router/header_parser.h"
      33             : #include "source/common/router/metadatamatchcriteria_impl.h"
      34             : #include "source/common/router/router_ratelimit.h"
      35             : #include "source/common/router/tls_context_match_criteria_impl.h"
      36             : #include "source/common/stats/symbol_table.h"
      37             : 
      38             : #include "absl/container/node_hash_map.h"
      39             : #include "absl/types/optional.h"
      40             : 
      41             : namespace Envoy {
      42             : namespace Router {
      43             : 
      44             : using RouteMetadataPack = Envoy::Config::MetadataPack<HttpRouteTypedMetadataFactory>;
      45             : using RouteMetadataPackPtr = Envoy::Config::MetadataPackPtr<HttpRouteTypedMetadataFactory>;
      46             : using DefaultRouteMetadataPack = ConstSingleton<RouteMetadataPack>;
      47             : 
      48             : /**
      49             :  * Original port from the authority header.
      50             :  */
      51             : class OriginalConnectPort : public StreamInfo::FilterState::Object {
      52             : public:
      53           0 :   explicit OriginalConnectPort(uint32_t port) : port_(port) {}
      54           0 :   const uint32_t& value() const { return port_; }
      55             :   static const std::string& key();
      56             : 
      57             : private:
      58             :   const uint32_t port_;
      59             : };
      60             : 
      61             : /**
      62             :  * Base interface for something that matches a header.
      63             :  */
      64             : class Matchable {
      65             : public:
      66        1684 :   virtual ~Matchable() = default;
      67             : 
      68             :   /**
      69             :    * See if this object matches the incoming headers.
      70             :    * @param headers supplies the headers to match.
      71             :    * @param random_value supplies the random seed to use if a runtime choice is required. This
      72             :    *        allows stable choices between calls if desired.
      73             :    * @return true if input headers match this object.
      74             :    */
      75             :   virtual RouteConstSharedPtr matches(const Http::RequestHeaderMap& headers,
      76             :                                       const StreamInfo::StreamInfo& stream_info,
      77             :                                       uint64_t random_value) const PURE;
      78             : 
      79             :   // By default, matchers do not support null Path headers.
      80           0 :   virtual bool supportsPathlessHeaders() const { return false; }
      81             : };
      82             : 
      83             : class PerFilterConfigs : public Logger::Loggable<Logger::Id::http> {
      84             : public:
      85             :   struct FilterConfig {
      86             :     RouteSpecificFilterConfigConstSharedPtr config_;
      87             :     bool disabled_{};
      88             :   };
      89             : 
      90             :   PerFilterConfigs(const Protobuf::Map<std::string, ProtobufWkt::Any>& typed_configs,
      91             :                    Server::Configuration::ServerFactoryContext& factory_context,
      92             :                    ProtobufMessage::ValidationVisitor& validator);
      93             : 
      94             :   const RouteSpecificFilterConfig* get(const std::string& name) const;
      95             : 
      96             :   /**
      97             :    * @return true if the filter is explicitly disabled for this route or virtual host, false
      98             :    * if the filter is explicitly enabled. If the filter is not explicitly enabled or disabled,
      99             :    * returns absl::nullopt.
     100             :    */
     101             :   absl::optional<bool> disabled(absl::string_view name) const;
     102             : 
     103             : private:
     104             :   RouteSpecificFilterConfigConstSharedPtr
     105             :   createRouteSpecificFilterConfig(const std::string& name, const ProtobufWkt::Any& typed_config,
     106             :                                   bool is_optional,
     107             :                                   Server::Configuration::ServerFactoryContext& factory_context,
     108             :                                   ProtobufMessage::ValidationVisitor& validator);
     109             :   absl::flat_hash_map<std::string, FilterConfig> configs_;
     110             : };
     111             : 
     112             : class RouteEntryImplBase;
     113             : using RouteEntryImplBaseConstSharedPtr = std::shared_ptr<const RouteEntryImplBase>;
     114             : 
     115             : /**
     116             :  * Direct response entry that does an SSL redirect.
     117             :  */
     118             : class SslRedirector : public DirectResponseEntry {
     119             : public:
     120             :   // Router::DirectResponseEntry
     121             :   void finalizeResponseHeaders(Http::ResponseHeaderMap&,
     122           0 :                                const StreamInfo::StreamInfo&) const override {}
     123             :   Http::HeaderTransforms responseHeaderTransforms(const StreamInfo::StreamInfo&,
     124           0 :                                                   bool) const override {
     125           0 :     return {};
     126           0 :   }
     127             :   std::string newUri(const Http::RequestHeaderMap& headers) const override;
     128           0 :   void rewritePathHeader(Http::RequestHeaderMap&, bool) const override {}
     129           0 :   Http::Code responseCode() const override { return Http::Code::MovedPermanently; }
     130           0 :   const std::string& responseBody() const override { return EMPTY_STRING; }
     131             : };
     132             : 
     133             : class SslRedirectRoute : public Route {
     134             : public:
     135             :   // Router::Route
     136           0 :   const DirectResponseEntry* directResponseEntry() const override { return &SSL_REDIRECTOR; }
     137           0 :   const RouteEntry* routeEntry() const override { return nullptr; }
     138           0 :   const Decorator* decorator() const override { return nullptr; }
     139           0 :   const RouteTracing* tracingConfig() const override { return nullptr; }
     140           0 :   const RouteSpecificFilterConfig* mostSpecificPerFilterConfig(const std::string&) const override {
     141           0 :     return nullptr;
     142           0 :   }
     143           0 :   absl::optional<bool> filterDisabled(absl::string_view) const override { return {}; }
     144             :   void traversePerFilterConfig(
     145             :       const std::string&,
     146           0 :       std::function<void(const Router::RouteSpecificFilterConfig&)>) const override {}
     147           0 :   const envoy::config::core::v3::Metadata& metadata() const override { return metadata_; }
     148           0 :   const Envoy::Config::TypedMetadata& typedMetadata() const override { return typed_metadata_; }
     149           0 :   const std::string& routeName() const override { return EMPTY_STRING; }
     150             : 
     151             : private:
     152             :   static const SslRedirector SSL_REDIRECTOR;
     153             :   static const envoy::config::core::v3::Metadata metadata_;
     154             :   static const Envoy::Config::TypedMetadataImpl<Envoy::Config::TypedMetadataFactory>
     155             :       typed_metadata_;
     156             : };
     157             : 
     158             : /**
     159             :  * Implementation of CorsPolicy that reads from the proto route and virtual host config.
     160             :  * TODO(wbpcode): move all cors interfaces and implementation to 'extensions/filters/http/cors'.
     161             :  */
     162             : template <class ProtoType> class CorsPolicyImplBase : public CorsPolicy {
     163             : public:
     164             :   CorsPolicyImplBase(const ProtoType& config, Runtime::Loader& loader)
     165             :       : config_(config), loader_(loader), allow_methods_(config.allow_methods()),
     166             :         allow_headers_(config.allow_headers()), expose_headers_(config.expose_headers()),
     167           4 :         max_age_(config.max_age()) {
     168           4 :     for (const auto& string_match : config.allow_origin_string_match()) {
     169           4 :       allow_origins_.push_back(
     170           4 :           std::make_unique<Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>>(
     171           4 :               string_match));
     172           4 :     }
     173           4 :     if (config.has_allow_credentials()) {
     174           4 :       allow_credentials_ = PROTOBUF_GET_WRAPPED_REQUIRED(config, allow_credentials);
     175           4 :     }
     176           4 :     if (config.has_allow_private_network_access()) {
     177           2 :       allow_private_network_access_ =
     178           2 :           PROTOBUF_GET_WRAPPED_REQUIRED(config, allow_private_network_access);
     179           2 :     }
     180           4 :   }
     181             : 
     182             :   // Router::CorsPolicy
     183           0 :   const std::vector<Matchers::StringMatcherPtr>& allowOrigins() const override {
     184           0 :     return allow_origins_;
     185           0 :   };
     186           0 :   const std::string& allowMethods() const override { return allow_methods_; };
     187           0 :   const std::string& allowHeaders() const override { return allow_headers_; };
     188           0 :   const std::string& exposeHeaders() const override { return expose_headers_; };
     189           0 :   const std::string& maxAge() const override { return max_age_; };
     190           0 :   const absl::optional<bool>& allowCredentials() const override { return allow_credentials_; };
     191           0 :   const absl::optional<bool>& allowPrivateNetworkAccess() const override {
     192           0 :     return allow_private_network_access_;
     193           0 :   };
     194           0 :   bool enabled() const override {
     195           0 :     if (config_.has_filter_enabled()) {
     196           0 :       const auto& filter_enabled = config_.filter_enabled();
     197           0 :       return loader_.snapshot().featureEnabled(filter_enabled.runtime_key(),
     198           0 :                                                filter_enabled.default_value());
     199           0 :     }
     200           0 :     return true;
     201           0 :   };
     202           0 :   bool shadowEnabled() const override {
     203           0 :     if (config_.has_shadow_enabled()) {
     204           0 :       const auto& shadow_enabled = config_.shadow_enabled();
     205           0 :       return loader_.snapshot().featureEnabled(shadow_enabled.runtime_key(),
     206           0 :                                                shadow_enabled.default_value());
     207           0 :     }
     208           0 :     return false;
     209           0 :   };
     210             : 
     211             : private:
     212             :   const ProtoType config_;
     213             :   Runtime::Loader& loader_;
     214             :   std::vector<Matchers::StringMatcherPtr> allow_origins_;
     215             :   const std::string allow_methods_;
     216             :   const std::string allow_headers_;
     217             :   const std::string expose_headers_;
     218             :   const std::string max_age_;
     219             :   absl::optional<bool> allow_credentials_{};
     220             :   absl::optional<bool> allow_private_network_access_{};
     221             : };
     222             : using CorsPolicyImpl = CorsPolicyImplBase<envoy::config::route::v3::CorsPolicy>;
     223             : 
     224             : using RetryPolicyConstOptRef = const OptRef<const envoy::config::route::v3::RetryPolicy>;
     225             : using HedgePolicyConstOptRef = const OptRef<const envoy::config::route::v3::HedgePolicy>;
     226             : 
     227             : class ConfigImpl;
     228             : class CommonConfigImpl;
     229             : using CommonConfigSharedPtr = std::shared_ptr<CommonConfigImpl>;
     230             : 
     231             : /**
     232             :  * Implementation of VirtualHost that reads from the proto config. This class holds all shared
     233             :  * data for all routes in the virtual host.
     234             :  */
     235             : class CommonVirtualHostImpl : public VirtualHost, Logger::Loggable<Logger::Id::router> {
     236             : public:
     237             :   CommonVirtualHostImpl(const envoy::config::route::v3::VirtualHost& virtual_host,
     238             :                         const CommonConfigSharedPtr& global_route_config,
     239             :                         Server::Configuration::ServerFactoryContext& factory_context,
     240             :                         Stats::Scope& scope, ProtobufMessage::ValidationVisitor& validator);
     241             : 
     242             :   const VirtualCluster* virtualClusterFromEntries(const Http::HeaderMap& headers) const;
     243        3381 :   const CommonConfigImpl& globalRouteConfig() const { return *global_route_config_; }
     244         196 :   const HeaderParser& requestHeaderParser() const {
     245         196 :     if (request_headers_parser_ != nullptr) {
     246           1 :       return *request_headers_parser_;
     247           1 :     }
     248         195 :     return HeaderParser::defaultParser();
     249         196 :   }
     250         335 :   const HeaderParser& responseHeaderParser() const {
     251         335 :     if (response_headers_parser_ != nullptr) {
     252           0 :       return *response_headers_parser_;
     253           0 :     }
     254         335 :     return HeaderParser::defaultParser();
     255         335 :   }
     256             :   absl::optional<bool> filterDisabled(absl::string_view config_name) const;
     257             : 
     258             :   // Router::VirtualHost
     259           0 :   const CorsPolicy* corsPolicy() const override { return cors_policy_.get(); }
     260         209 :   Stats::StatName statName() const override { return stat_name_storage_.statName(); }
     261           0 :   const RateLimitPolicy& rateLimitPolicy() const override {
     262           0 :     if (rate_limit_policy_ != nullptr) {
     263           0 :       return *rate_limit_policy_;
     264           0 :     }
     265           0 :     return DefaultRateLimitPolicy::get();
     266           0 :   }
     267             :   const CommonConfig& routeConfig() const override;
     268             :   const RouteSpecificFilterConfig* mostSpecificPerFilterConfig(const std::string&) const override;
     269         183 :   bool includeAttemptCountInRequest() const override { return include_attempt_count_in_request_; }
     270         183 :   bool includeAttemptCountInResponse() const override { return include_attempt_count_in_response_; }
     271         183 :   bool includeIsTimeoutRetryHeader() const override { return include_is_timeout_retry_header_; }
     272        1617 :   const std::vector<ShadowPolicyPtr>& shadowPolicies() const { return shadow_policies_; }
     273        1684 :   RetryPolicyConstOptRef retryPolicy() const {
     274        1684 :     if (retry_policy_ != nullptr) {
     275          26 :       return *retry_policy_;
     276          26 :     }
     277        1658 :     return absl::nullopt;
     278        1684 :   }
     279        1684 :   HedgePolicyConstOptRef hedgePolicy() const {
     280        1684 :     if (hedge_policy_ != nullptr) {
     281          18 :       return *hedge_policy_;
     282          18 :     }
     283        1666 :     return absl::nullopt;
     284        1684 :   }
     285        1644 :   uint32_t retryShadowBufferLimit() const override { return retry_shadow_buffer_limit_; }
     286             : 
     287             :   void traversePerFilterConfig(
     288             :       const std::string& filter_name,
     289             :       std::function<void(const Router::RouteSpecificFilterConfig&)> cb) const override;
     290             :   const envoy::config::core::v3::Metadata& metadata() const override;
     291             :   const Envoy::Config::TypedMetadata& typedMetadata() const override;
     292             : 
     293             : private:
     294             :   struct StatNameProvider {
     295             :     StatNameProvider(absl::string_view name, Stats::SymbolTable& symbol_table)
     296           0 :         : stat_name_storage_(name, symbol_table) {}
     297             :     Stats::StatNameManagedStorage stat_name_storage_;
     298             :   };
     299             : 
     300             :   struct VirtualClusterBase : public VirtualCluster {
     301             :   public:
     302             :     VirtualClusterBase(const absl::optional<std::string>& name, Stats::StatName stat_name,
     303             :                        Stats::ScopeSharedPtr&& scope, const VirtualClusterStatNames& stat_names)
     304             :         : name_(name), stat_name_(stat_name), scope_(std::move(scope)),
     305           0 :           stats_(generateStats(*scope_, stat_names)) {}
     306             : 
     307             :     // Router::VirtualCluster
     308             :     // name_ and stat_name_ are two different representations for the same string, retained in
     309             :     // memory to avoid symbol-table locks that would be needed when converting on-the-fly.
     310           0 :     const absl::optional<std::string>& name() const override { return name_; }
     311           0 :     Stats::StatName statName() const override { return stat_name_; }
     312           0 :     VirtualClusterStats& stats() const override { return stats_; }
     313             : 
     314             :   private:
     315             :     const absl::optional<std::string> name_;
     316             :     const Stats::StatName stat_name_;
     317             :     Stats::ScopeSharedPtr scope_;
     318             :     mutable VirtualClusterStats stats_;
     319             :   };
     320             : 
     321             :   struct VirtualClusterEntry : public StatNameProvider, public VirtualClusterBase {
     322             :     VirtualClusterEntry(const envoy::config::route::v3::VirtualCluster& virtual_cluster,
     323             :                         Stats::Scope& scope, const VirtualClusterStatNames& stat_names);
     324             :     std::vector<Http::HeaderUtility::HeaderDataPtr> headers_;
     325             :   };
     326             : 
     327             :   struct CatchAllVirtualCluster : public VirtualClusterBase {
     328             :     CatchAllVirtualCluster(Stats::Scope& scope, const VirtualClusterStatNames& stat_names)
     329             :         : VirtualClusterBase(absl::nullopt, stat_names.other_,
     330           0 :                              scope.scopeFromStatName(stat_names.other_), stat_names) {}
     331             :   };
     332             : 
     333             :   const Stats::StatNameManagedStorage stat_name_storage_;
     334             :   Stats::ScopeSharedPtr vcluster_scope_;
     335             :   std::vector<VirtualClusterEntry> virtual_clusters_;
     336             :   std::unique_ptr<const RateLimitPolicyImpl> rate_limit_policy_;
     337             :   std::vector<ShadowPolicyPtr> shadow_policies_;
     338             :   std::unique_ptr<const CorsPolicyImpl> cors_policy_;
     339             :   // Keep an copy of the shared pointer to the shared part of the route config. This is needed
     340             :   // to keep the shared part alive while the virtual host is alive.
     341             :   const CommonConfigSharedPtr global_route_config_;
     342             :   HeaderParserPtr request_headers_parser_;
     343             :   HeaderParserPtr response_headers_parser_;
     344             :   PerFilterConfigs per_filter_configs_;
     345             :   std::unique_ptr<envoy::config::route::v3::RetryPolicy> retry_policy_;
     346             :   std::unique_ptr<envoy::config::route::v3::HedgePolicy> hedge_policy_;
     347             :   std::unique_ptr<const CatchAllVirtualCluster> virtual_cluster_catch_all_;
     348             :   RouteMetadataPackPtr metadata_;
     349             :   // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
     350             :   uint32_t retry_shadow_buffer_limit_{std::numeric_limits<uint32_t>::max()};
     351             :   const bool include_attempt_count_in_request_ : 1;
     352             :   const bool include_attempt_count_in_response_ : 1;
     353             :   const bool include_is_timeout_retry_header_ : 1;
     354             : };
     355             : 
     356             : using CommonVirtualHostSharedPtr = std::shared_ptr<CommonVirtualHostImpl>;
     357             : 
     358             : /**
     359             :  * Virtual host that holds a collection of routes.
     360             :  */
     361             : class VirtualHostImpl : Logger::Loggable<Logger::Id::router> {
     362             : public:
     363             :   VirtualHostImpl(
     364             :       const envoy::config::route::v3::VirtualHost& virtual_host,
     365             :       const CommonConfigSharedPtr& global_route_config,
     366             :       Server::Configuration::ServerFactoryContext& factory_context, Stats::Scope& scope,
     367             :       ProtobufMessage::ValidationVisitor& validator,
     368             :       const absl::optional<Upstream::ClusterManager::ClusterInfoMaps>& validation_clusters);
     369             : 
     370             :   RouteConstSharedPtr getRouteFromEntries(const RouteCallback& cb,
     371             :                                           const Http::RequestHeaderMap& headers,
     372             :                                           const StreamInfo::StreamInfo& stream_info,
     373             :                                           uint64_t random_value) const;
     374             : 
     375             :   RouteConstSharedPtr
     376             :   getRouteFromRoutes(const RouteCallback& cb, const Http::RequestHeaderMap& headers,
     377             :                      const StreamInfo::StreamInfo& stream_info, uint64_t random_value,
     378             :                      absl::Span<const RouteEntryImplBaseConstSharedPtr> routes) const;
     379             : 
     380             : private:
     381             :   enum class SslRequirements : uint8_t { None, ExternalOnly, All };
     382             : 
     383             :   static const std::shared_ptr<const SslRedirectRoute> SSL_REDIRECT_ROUTE;
     384             : 
     385             :   CommonVirtualHostSharedPtr shared_virtual_host_;
     386             : 
     387             :   SslRequirements ssl_requirements_;
     388             : 
     389             :   std::vector<RouteEntryImplBaseConstSharedPtr> routes_;
     390             :   Matcher::MatchTreeSharedPtr<Http::HttpMatchingData> matcher_;
     391             : };
     392             : 
     393             : using VirtualHostSharedPtr = std::shared_ptr<VirtualHostImpl>;
     394             : 
     395             : /**
     396             :  * Implementation of RetryPolicy that reads from the proto route or virtual host config.
     397             :  */
     398             : class RetryPolicyImpl : public RetryPolicy {
     399             : 
     400             : public:
     401             :   RetryPolicyImpl(const envoy::config::route::v3::RetryPolicy& retry_policy,
     402             :                   ProtobufMessage::ValidationVisitor& validation_visitor,
     403             :                   Upstream::RetryExtensionFactoryContext& factory_context);
     404          74 :   RetryPolicyImpl() = default;
     405             : 
     406             :   // Router::RetryPolicy
     407         251 :   std::chrono::milliseconds perTryTimeout() const override { return per_try_timeout_; }
     408         251 :   std::chrono::milliseconds perTryIdleTimeout() const override { return per_try_idle_timeout_; }
     409           0 :   uint32_t numRetries() const override { return num_retries_; }
     410         251 :   uint32_t retryOn() const override { return retry_on_; }
     411             :   std::vector<Upstream::RetryHostPredicateSharedPtr> retryHostPredicates() const override;
     412             :   Upstream::RetryPrioritySharedPtr retryPriority() const override;
     413             :   absl::Span<const Upstream::RetryOptionsPredicateConstSharedPtr>
     414           0 :   retryOptionsPredicates() const override {
     415           0 :     return retry_options_predicates_;
     416           0 :   }
     417           0 :   uint32_t hostSelectionMaxAttempts() const override { return host_selection_attempts_; }
     418           0 :   const std::vector<uint32_t>& retriableStatusCodes() const override {
     419           0 :     return retriable_status_codes_;
     420           0 :   }
     421           0 :   const std::vector<Http::HeaderMatcherSharedPtr>& retriableHeaders() const override {
     422           0 :     return retriable_headers_;
     423           0 :   }
     424           0 :   const std::vector<Http::HeaderMatcherSharedPtr>& retriableRequestHeaders() const override {
     425           0 :     return retriable_request_headers_;
     426           0 :   }
     427           0 :   absl::optional<std::chrono::milliseconds> baseInterval() const override { return base_interval_; }
     428           0 :   absl::optional<std::chrono::milliseconds> maxInterval() const override { return max_interval_; }
     429           0 :   const std::vector<ResetHeaderParserSharedPtr>& resetHeaders() const override {
     430           0 :     return reset_headers_;
     431           0 :   }
     432           0 :   std::chrono::milliseconds resetMaxInterval() const override { return reset_max_interval_; }
     433             : 
     434             : private:
     435             :   std::chrono::milliseconds per_try_timeout_{0};
     436             :   std::chrono::milliseconds per_try_idle_timeout_{0};
     437             :   // We set the number of retries to 1 by default (i.e. when no route or vhost level retry policy is
     438             :   // set) so that when retries get enabled through the x-envoy-retry-on header we default to 1
     439             :   // retry.
     440             :   uint32_t num_retries_{1};
     441             :   uint32_t retry_on_{};
     442             :   // Each pair contains the name and config proto to be used to create the RetryHostPredicates
     443             :   // that should be used when with this policy.
     444             :   std::vector<std::pair<Upstream::RetryHostPredicateFactory&, ProtobufTypes::MessagePtr>>
     445             :       retry_host_predicate_configs_;
     446             :   Upstream::RetryPrioritySharedPtr retry_priority_;
     447             :   // Name and config proto to use to create the RetryPriority to use with this policy. Default
     448             :   // initialized when no RetryPriority should be used.
     449             :   std::pair<Upstream::RetryPriorityFactory*, ProtobufTypes::MessagePtr> retry_priority_config_;
     450             :   uint32_t host_selection_attempts_{1};
     451             :   std::vector<uint32_t> retriable_status_codes_;
     452             :   std::vector<Http::HeaderMatcherSharedPtr> retriable_headers_;
     453             :   std::vector<Http::HeaderMatcherSharedPtr> retriable_request_headers_;
     454             :   absl::optional<std::chrono::milliseconds> base_interval_;
     455             :   absl::optional<std::chrono::milliseconds> max_interval_;
     456             :   std::vector<ResetHeaderParserSharedPtr> reset_headers_{};
     457             :   std::chrono::milliseconds reset_max_interval_{300000};
     458             :   ProtobufMessage::ValidationVisitor* validation_visitor_{};
     459             :   std::vector<Upstream::RetryOptionsPredicateConstSharedPtr> retry_options_predicates_;
     460             : };
     461             : using DefaultRetryPolicy = ConstSingleton<RetryPolicyImpl>;
     462             : 
     463             : /**
     464             :  * Implementation of ShadowPolicy that reads from the proto route config.
     465             :  */
     466             : class ShadowPolicyImpl : public ShadowPolicy {
     467             : public:
     468             :   using RequestMirrorPolicy = envoy::config::route::v3::RouteAction::RequestMirrorPolicy;
     469             :   explicit ShadowPolicyImpl(const RequestMirrorPolicy& config);
     470             : 
     471             :   // Router::ShadowPolicy
     472           0 :   const std::string& cluster() const override { return cluster_; }
     473           0 :   const Http::LowerCaseString& clusterHeader() const override { return cluster_header_; }
     474           0 :   const std::string& runtimeKey() const override { return runtime_key_; }
     475           0 :   const envoy::type::v3::FractionalPercent& defaultValue() const override { return default_value_; }
     476           0 :   bool traceSampled() const override { return trace_sampled_; }
     477             : 
     478             : private:
     479             :   const std::string cluster_;
     480             :   const Http::LowerCaseString cluster_header_;
     481             :   std::string runtime_key_;
     482             :   envoy::type::v3::FractionalPercent default_value_;
     483             :   bool trace_sampled_;
     484             : };
     485             : 
     486             : /**
     487             :  * Implementation of HedgePolicy that reads from the proto route or virtual host config.
     488             :  */
     489             : class HedgePolicyImpl : public HedgePolicy {
     490             : 
     491             : public:
     492             :   explicit HedgePolicyImpl(const envoy::config::route::v3::HedgePolicy& hedge_policy);
     493             :   HedgePolicyImpl();
     494             : 
     495             :   // Router::HedgePolicy
     496           0 :   uint32_t initialRequests() const override { return initial_requests_; }
     497           0 :   const envoy::type::v3::FractionalPercent& additionalRequestChance() const override {
     498           0 :     return additional_request_chance_;
     499           0 :   }
     500         183 :   bool hedgeOnPerTryTimeout() const override { return hedge_on_per_try_timeout_; }
     501             : 
     502             : private:
     503             :   const uint32_t initial_requests_;
     504             :   const envoy::type::v3::FractionalPercent additional_request_chance_;
     505             :   const bool hedge_on_per_try_timeout_;
     506             : };
     507             : using DefaultHedgePolicy = ConstSingleton<HedgePolicyImpl>;
     508             : 
     509             : /**
     510             :  * Implementation of Decorator that reads from the proto route decorator.
     511             :  */
     512             : class DecoratorImpl : public Decorator {
     513             : public:
     514             :   explicit DecoratorImpl(const envoy::config::route::v3::Decorator& decorator);
     515             : 
     516             :   // Decorator::apply
     517             :   void apply(Tracing::Span& span) const override;
     518             : 
     519             :   // Decorator::getOperation
     520             :   const std::string& getOperation() const override;
     521             : 
     522             :   // Decorator::getOperation
     523             :   bool propagate() const override;
     524             : 
     525             : private:
     526             :   const std::string operation_;
     527             :   const bool propagate_;
     528             : };
     529             : 
     530             : /**
     531             :  * Implementation of RouteTracing that reads from the proto route tracing.
     532             :  */
     533             : class RouteTracingImpl : public RouteTracing {
     534             : public:
     535             :   explicit RouteTracingImpl(const envoy::config::route::v3::Tracing& tracing);
     536             : 
     537             :   // Tracing::getClientSampling
     538             :   const envoy::type::v3::FractionalPercent& getClientSampling() const override;
     539             : 
     540             :   // Tracing::getRandomSampling
     541             :   const envoy::type::v3::FractionalPercent& getRandomSampling() const override;
     542             : 
     543             :   // Tracing::getOverallSampling
     544             :   const envoy::type::v3::FractionalPercent& getOverallSampling() const override;
     545             : 
     546             :   const Tracing::CustomTagMap& getCustomTags() const override;
     547             : 
     548             : private:
     549             :   envoy::type::v3::FractionalPercent client_sampling_;
     550             :   envoy::type::v3::FractionalPercent random_sampling_;
     551             :   envoy::type::v3::FractionalPercent overall_sampling_;
     552             :   Tracing::CustomTagMap custom_tags_;
     553             : };
     554             : 
     555             : /**
     556             :  * Implementation of InternalRedirectPolicy that reads from the proto
     557             :  * InternalRedirectPolicy of the RouteAction.
     558             :  */
     559             : class InternalRedirectPolicyImpl : public InternalRedirectPolicy {
     560             : public:
     561             :   // Constructor that enables internal redirect with policy_config controlling the configurable
     562             :   // behaviors.
     563             :   InternalRedirectPolicyImpl(const envoy::config::route::v3::InternalRedirectPolicy& policy_config,
     564             :                              ProtobufMessage::ValidationVisitor& validator,
     565             :                              absl::string_view current_route_name);
     566             :   // Default constructor that disables internal redirect.
     567          51 :   InternalRedirectPolicyImpl() = default;
     568             : 
     569         737 :   bool enabled() const override { return enabled_; }
     570             : 
     571           0 :   bool shouldRedirectForResponseCode(const Http::Code& response_code) const override {
     572           0 :     return redirect_response_codes_.contains(response_code);
     573           0 :   }
     574             : 
     575             :   std::vector<InternalRedirectPredicateSharedPtr> predicates() const override;
     576             :   const std::vector<Http::LowerCaseString>& responseHeadersToCopy() const override;
     577             : 
     578           0 :   uint32_t maxInternalRedirects() const override { return max_internal_redirects_; }
     579             : 
     580           0 :   bool isCrossSchemeRedirectAllowed() const override { return allow_cross_scheme_redirect_; }
     581             : 
     582             : private:
     583             :   absl::flat_hash_set<Http::Code> buildRedirectResponseCodes(
     584             :       const envoy::config::route::v3::InternalRedirectPolicy& policy_config) const;
     585             : 
     586             :   const std::string current_route_name_;
     587             :   const absl::flat_hash_set<Http::Code> redirect_response_codes_;
     588             :   std::vector<std::pair<InternalRedirectPredicateFactory*, ProtobufTypes::MessagePtr>>
     589             :       predicate_factories_;
     590             :   // Vector of header names (as a lower case string to simplify use
     591             :   // later on), to copy from the response that triggers the redirect
     592             :   // into the following request.
     593             :   std::vector<Http::LowerCaseString> response_headers_to_copy_;
     594             :   // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
     595             :   const uint32_t max_internal_redirects_{1};
     596             :   const bool enabled_{false};
     597             :   const bool allow_cross_scheme_redirect_{false};
     598             : };
     599             : using DefaultInternalRedirectPolicy = ConstSingleton<InternalRedirectPolicyImpl>;
     600             : 
     601             : /**
     602             :  * Base implementation for all route entries.q
     603             :  */
     604             : class RouteEntryImplBase : public RouteEntryAndRoute,
     605             :                            public Matchable,
     606             :                            public DirectResponseEntry,
     607             :                            public PathMatchCriterion,
     608             :                            public std::enable_shared_from_this<RouteEntryImplBase>,
     609             :                            Logger::Loggable<Logger::Id::router> {
     610             : public:
     611             :   /**
     612             :    * @throw EnvoyException with reason if the route configuration contains any errors
     613             :    */
     614             :   RouteEntryImplBase(const CommonVirtualHostSharedPtr& vhost,
     615             :                      const envoy::config::route::v3::Route& route,
     616             :                      Server::Configuration::ServerFactoryContext& factory_context,
     617             :                      ProtobufMessage::ValidationVisitor& validator);
     618             : 
     619        4911 :   bool isDirectResponse() const { return direct_response_code_.has_value(); }
     620             : 
     621         400 :   bool isRedirect() const {
     622         400 :     if (!isDirectResponse()) {
     623         198 :       return false;
     624         198 :     }
     625         202 :     if (redirect_config_ == nullptr) {
     626         202 :       return false;
     627         202 :     }
     628           0 :     return !redirect_config_->host_redirect_.empty() || !redirect_config_->path_redirect_.empty() ||
     629           0 :            !redirect_config_->prefix_rewrite_redirect_.empty() ||
     630           0 :            redirect_config_->regex_rewrite_redirect_ != nullptr;
     631         202 :   }
     632             : 
     633             :   bool matchRoute(const Http::RequestHeaderMap& headers, const StreamInfo::StreamInfo& stream_info,
     634             :                   uint64_t random_value) const;
     635             :   void validateClusters(const Upstream::ClusterManager::ClusterInfoMaps& cluster_info_maps) const;
     636             : 
     637             :   // Router::RouteEntry
     638             :   const std::string& clusterName() const override;
     639         183 :   const RouteStatsContextOptRef routeStatsContext() const override {
     640         183 :     if (route_stats_context_ != nullptr) {
     641           0 :       return *route_stats_context_;
     642           0 :     }
     643         183 :     return RouteStatsContextOptRef();
     644         183 :   }
     645           0 :   Http::Code clusterNotFoundResponseCode() const override {
     646           0 :     return cluster_not_found_response_code_;
     647           0 :   }
     648           0 :   const CorsPolicy* corsPolicy() const override { return cors_policy_.get(); }
     649         196 :   const HeaderParser& requestHeaderParser() const {
     650         196 :     if (request_headers_parser_ != nullptr) {
     651           3 :       return *request_headers_parser_;
     652           3 :     }
     653         193 :     return HeaderParser::defaultParser();
     654         196 :   }
     655         335 :   const HeaderParser& responseHeaderParser() const {
     656         335 :     if (response_headers_parser_ != nullptr) {
     657           0 :       return *response_headers_parser_;
     658           0 :     }
     659         335 :     return HeaderParser::defaultParser();
     660         335 :   }
     661             :   void finalizeRequestHeaders(Http::RequestHeaderMap& headers,
     662             :                               const StreamInfo::StreamInfo& stream_info,
     663             :                               bool insert_envoy_original_path) const override;
     664             :   Http::HeaderTransforms requestHeaderTransforms(const StreamInfo::StreamInfo& stream_info,
     665             :                                                  bool do_formatting = true) const override;
     666             :   void finalizeResponseHeaders(Http::ResponseHeaderMap& headers,
     667             :                                const StreamInfo::StreamInfo& stream_info) const override;
     668             :   Http::HeaderTransforms responseHeaderTransforms(const StreamInfo::StreamInfo& stream_info,
     669             :                                                   bool do_formatting = true) const override;
     670           0 :   const Http::HashPolicy* hashPolicy() const override { return hash_policy_.get(); }
     671             : 
     672         183 :   const HedgePolicy& hedgePolicy() const override {
     673         183 :     if (hedge_policy_ != nullptr) {
     674           0 :       return *hedge_policy_;
     675           0 :     }
     676         183 :     return DefaultHedgePolicy::get();
     677         183 :   }
     678             : 
     679           0 :   const MetadataMatchCriteria* metadataMatchCriteria() const override {
     680           0 :     return metadata_match_criteria_.get();
     681           0 :   }
     682         674 :   const TlsContextMatchCriteria* tlsContextMatchCriteria() const override {
     683         674 :     return tls_context_match_criteria_.get();
     684         674 :   }
     685         366 :   Upstream::ResourcePriority priority() const override { return priority_; }
     686           0 :   const RateLimitPolicy& rateLimitPolicy() const override {
     687           0 :     if (rate_limit_policy_ != nullptr) {
     688           0 :       return *rate_limit_policy_;
     689           0 :     }
     690           0 :     return DefaultRateLimitPolicy::get();
     691           0 :   }
     692         549 :   const RetryPolicy& retryPolicy() const override {
     693         549 :     if (retry_policy_ != nullptr) {
     694           0 :       return *retry_policy_;
     695           0 :     }
     696         549 :     return DefaultRetryPolicy::get();
     697         549 :   }
     698         238 :   const InternalRedirectPolicy& internalRedirectPolicy() const override {
     699         238 :     if (internal_redirect_policy_ != nullptr) {
     700           0 :       return *internal_redirect_policy_;
     701           0 :     }
     702         238 :     return DefaultInternalRedirectPolicy::get();
     703         238 :   }
     704             : 
     705           0 :   const PathMatcherSharedPtr& pathMatcher() const override { return path_matcher_; }
     706           0 :   const PathRewriterSharedPtr& pathRewriter() const override { return path_rewriter_; }
     707             : 
     708         183 :   uint32_t retryShadowBufferLimit() const override { return retry_shadow_buffer_limit_; }
     709         756 :   const std::vector<ShadowPolicyPtr>& shadowPolicies() const override { return shadow_policies_; }
     710         183 :   const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const override {
     711         183 :     return vhost_->virtualClusterFromEntries(headers);
     712         183 :   }
     713         183 :   std::chrono::milliseconds timeout() const override { return timeout_; }
     714         183 :   bool usingNewTimeouts() const override { return using_new_timeouts_; }
     715             : 
     716             :   // `OptionalTimeouts` manages various `optional` values. We pack them in a
     717             :   // separate data structure for memory efficiency -- avoiding overhead of
     718             :   // `absl::optional` per variable, and avoiding overhead of storing unset
     719             :   // timeouts.
     720             :   enum class OptionalTimeoutNames {
     721             :     IdleTimeout = 0,
     722             :     MaxStreamDuration,
     723             :     GrpcTimeoutHeaderMax,
     724             :     GrpcTimeoutHeaderOffset,
     725             :     MaxGrpcTimeout,
     726             :     GrpcTimeoutOffset
     727             :   };
     728             :   using OptionalTimeouts = PackedStruct<std::chrono::milliseconds, 6, OptionalTimeoutNames>;
     729             : 
     730         185 :   absl::optional<std::chrono::milliseconds> idleTimeout() const override {
     731         185 :     return getOptionalTimeout<OptionalTimeoutNames::IdleTimeout>();
     732         185 :   }
     733         185 :   absl::optional<std::chrono::milliseconds> maxStreamDuration() const override {
     734         185 :     return getOptionalTimeout<OptionalTimeoutNames::MaxStreamDuration>();
     735         185 :   }
     736           0 :   absl::optional<std::chrono::milliseconds> grpcTimeoutHeaderMax() const override {
     737           0 :     return getOptionalTimeout<OptionalTimeoutNames::GrpcTimeoutHeaderMax>();
     738           0 :   }
     739           0 :   absl::optional<std::chrono::milliseconds> grpcTimeoutHeaderOffset() const override {
     740           0 :     return getOptionalTimeout<OptionalTimeoutNames::GrpcTimeoutHeaderOffset>();
     741           0 :   }
     742           0 :   absl::optional<std::chrono::milliseconds> maxGrpcTimeout() const override {
     743           0 :     return getOptionalTimeout<OptionalTimeoutNames::MaxGrpcTimeout>();
     744           0 :   }
     745           0 :   absl::optional<std::chrono::milliseconds> grpcTimeoutOffset() const override {
     746           0 :     return getOptionalTimeout<OptionalTimeoutNames::GrpcTimeoutOffset>();
     747           0 :   }
     748             : 
     749         387 :   const VirtualHost& virtualHost() const override { return *vhost_; }
     750         134 :   bool autoHostRewrite() const override { return auto_host_rewrite_; }
     751           0 :   bool appendXfh() const override { return append_xfh_; }
     752           0 :   const std::multimap<std::string, std::string>& opaqueConfig() const override {
     753           0 :     return opaque_config_;
     754           0 :   }
     755           0 :   bool includeVirtualHostRateLimits() const override { return include_vh_rate_limits_; }
     756             :   const envoy::config::core::v3::Metadata& metadata() const override;
     757             :   const Envoy::Config::TypedMetadata& typedMetadata() const override;
     758           0 :   const PathMatchCriterion& pathMatchCriterion() const override { return *this; }
     759         183 :   bool includeAttemptCountInRequest() const override {
     760         183 :     return vhost_->includeAttemptCountInRequest();
     761         183 :   }
     762         183 :   bool includeAttemptCountInResponse() const override {
     763         183 :     return vhost_->includeAttemptCountInResponse();
     764         183 :   }
     765         183 :   const ConnectConfigOptRef connectConfig() const override {
     766         183 :     if (connect_config_ != nullptr) {
     767           0 :       return *connect_config_;
     768           0 :     }
     769         183 :     return absl::nullopt;
     770         183 :   }
     771           0 :   const UpgradeMap& upgradeMap() const override { return upgrade_map_; }
     772         183 :   const EarlyDataPolicy& earlyDataPolicy() const override { return *early_data_policy_; }
     773             : 
     774             :   // Router::DirectResponseEntry
     775             :   std::string newUri(const Http::RequestHeaderMap& headers) const override;
     776           0 :   void rewritePathHeader(Http::RequestHeaderMap&, bool) const override {}
     777         606 :   Http::Code responseCode() const override { return direct_response_code_.value(); }
     778         202 :   const std::string& responseBody() const override { return direct_response_body_; }
     779             : 
     780             :   // Router::Route
     781             :   const DirectResponseEntry* directResponseEntry() const override;
     782             :   const RouteEntry* routeEntry() const override;
     783           0 :   const Decorator* decorator() const override { return decorator_.get(); }
     784           0 :   const RouteTracing* tracingConfig() const override { return route_tracing_.get(); }
     785             :   absl::optional<bool> filterDisabled(absl::string_view config_name) const override;
     786             :   const RouteSpecificFilterConfig*
     787           0 :   mostSpecificPerFilterConfig(const std::string& name) const override {
     788           0 :     auto* config = per_filter_configs_.get(name);
     789           0 :     return config ? config : vhost_->mostSpecificPerFilterConfig(name);
     790           0 :   }
     791             :   void traversePerFilterConfig(
     792             :       const std::string& filter_name,
     793             :       std::function<void(const Router::RouteSpecificFilterConfig&)> cb) const override;
     794           0 :   const std::string& routeName() const override { return route_name_; }
     795             : 
     796             :   // Sanitizes the |path| before passing it to PathMatcher, if configured, this method makes the
     797             :   // path matching to ignore the path-parameters.
     798             :   absl::string_view sanitizePathBeforePathMatching(const absl::string_view path) const;
     799             : 
     800             :   class DynamicRouteEntry : public RouteEntryAndRoute {
     801             :   public:
     802             :     DynamicRouteEntry(const RouteEntryAndRoute* parent, RouteConstSharedPtr owner,
     803             :                       const std::string& name)
     804         209 :         : parent_(parent), owner_(std::move(owner)), cluster_name_(name) {}
     805             : 
     806             :     // Router::RouteEntry
     807         262 :     const std::string& clusterName() const override { return cluster_name_; }
     808           0 :     Http::Code clusterNotFoundResponseCode() const override {
     809           0 :       return parent_->clusterNotFoundResponseCode();
     810           0 :     }
     811             : 
     812             :     absl::optional<std::string>
     813           0 :     currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const override {
     814           0 :       return parent_->currentUrlPathAfterRewrite(headers);
     815           0 :     }
     816             :     void finalizeRequestHeaders(Http::RequestHeaderMap& headers,
     817             :                                 const StreamInfo::StreamInfo& stream_info,
     818          13 :                                 bool insert_envoy_original_path) const override {
     819          13 :       return parent_->finalizeRequestHeaders(headers, stream_info, insert_envoy_original_path);
     820          13 :     }
     821             :     Http::HeaderTransforms requestHeaderTransforms(const StreamInfo::StreamInfo& stream_info,
     822           0 :                                                    bool do_formatting = true) const override {
     823           0 :       return parent_->requestHeaderTransforms(stream_info, do_formatting);
     824           0 :     }
     825             :     void finalizeResponseHeaders(Http::ResponseHeaderMap& headers,
     826           0 :                                  const StreamInfo::StreamInfo& stream_info) const override {
     827           0 :       return parent_->finalizeResponseHeaders(headers, stream_info);
     828           0 :     }
     829             :     Http::HeaderTransforms responseHeaderTransforms(const StreamInfo::StreamInfo& stream_info,
     830           0 :                                                     bool do_formatting = true) const override {
     831           0 :       return parent_->responseHeaderTransforms(stream_info, do_formatting);
     832           0 :     }
     833             : 
     834           0 :     const CorsPolicy* corsPolicy() const override { return parent_->corsPolicy(); }
     835           0 :     const Http::HashPolicy* hashPolicy() const override { return parent_->hashPolicy(); }
     836           0 :     const HedgePolicy& hedgePolicy() const override { return parent_->hedgePolicy(); }
     837           0 :     Upstream::ResourcePriority priority() const override { return parent_->priority(); }
     838           0 :     const RateLimitPolicy& rateLimitPolicy() const override { return parent_->rateLimitPolicy(); }
     839           0 :     const RetryPolicy& retryPolicy() const override { return parent_->retryPolicy(); }
     840           0 :     const InternalRedirectPolicy& internalRedirectPolicy() const override {
     841           0 :       return parent_->internalRedirectPolicy();
     842           0 :     }
     843           0 :     const PathMatcherSharedPtr& pathMatcher() const override { return parent_->pathMatcher(); }
     844           0 :     const PathRewriterSharedPtr& pathRewriter() const override { return parent_->pathRewriter(); }
     845           0 :     uint32_t retryShadowBufferLimit() const override { return parent_->retryShadowBufferLimit(); }
     846           0 :     const std::vector<ShadowPolicyPtr>& shadowPolicies() const override {
     847           0 :       return parent_->shadowPolicies();
     848           0 :     }
     849           0 :     std::chrono::milliseconds timeout() const override { return parent_->timeout(); }
     850           0 :     absl::optional<std::chrono::milliseconds> idleTimeout() const override {
     851           0 :       return parent_->idleTimeout();
     852           0 :     }
     853           0 :     bool usingNewTimeouts() const override { return parent_->usingNewTimeouts(); }
     854           0 :     absl::optional<std::chrono::milliseconds> maxStreamDuration() const override {
     855           0 :       return parent_->maxStreamDuration();
     856           0 :     }
     857           0 :     absl::optional<std::chrono::milliseconds> grpcTimeoutHeaderMax() const override {
     858           0 :       return parent_->grpcTimeoutHeaderMax();
     859           0 :     }
     860           0 :     absl::optional<std::chrono::milliseconds> grpcTimeoutHeaderOffset() const override {
     861           0 :       return parent_->grpcTimeoutHeaderOffset();
     862           0 :     }
     863           0 :     absl::optional<std::chrono::milliseconds> maxGrpcTimeout() const override {
     864           0 :       return parent_->maxGrpcTimeout();
     865           0 :     }
     866           0 :     absl::optional<std::chrono::milliseconds> grpcTimeoutOffset() const override {
     867           0 :       return parent_->grpcTimeoutOffset();
     868           0 :     }
     869           0 :     const MetadataMatchCriteria* metadataMatchCriteria() const override {
     870           0 :       return parent_->metadataMatchCriteria();
     871           0 :     }
     872           0 :     const TlsContextMatchCriteria* tlsContextMatchCriteria() const override {
     873           0 :       return parent_->tlsContextMatchCriteria();
     874           0 :     }
     875             : 
     876           0 :     const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const override {
     877           0 :       return parent_->virtualCluster(headers);
     878           0 :     }
     879             : 
     880           0 :     const std::multimap<std::string, std::string>& opaqueConfig() const override {
     881           0 :       return parent_->opaqueConfig();
     882           0 :     }
     883             : 
     884           0 :     const VirtualHost& virtualHost() const override { return parent_->virtualHost(); }
     885           0 :     bool autoHostRewrite() const override { return parent_->autoHostRewrite(); }
     886           0 :     bool appendXfh() const override { return parent_->appendXfh(); }
     887           0 :     bool includeVirtualHostRateLimits() const override {
     888           0 :       return parent_->includeVirtualHostRateLimits();
     889           0 :     }
     890           0 :     const envoy::config::core::v3::Metadata& metadata() const override {
     891           0 :       return parent_->metadata();
     892           0 :     }
     893           0 :     const Envoy::Config::TypedMetadata& typedMetadata() const override {
     894           0 :       return parent_->typedMetadata();
     895           0 :     }
     896           0 :     const PathMatchCriterion& pathMatchCriterion() const override {
     897           0 :       return parent_->pathMatchCriterion();
     898           0 :     }
     899             : 
     900           0 :     bool includeAttemptCountInRequest() const override {
     901           0 :       return parent_->includeAttemptCountInRequest();
     902           0 :     }
     903           0 :     bool includeAttemptCountInResponse() const override {
     904           0 :       return parent_->includeAttemptCountInResponse();
     905           0 :     }
     906           0 :     const ConnectConfigOptRef connectConfig() const override { return parent_->connectConfig(); }
     907           0 :     const RouteStatsContextOptRef routeStatsContext() const override {
     908           0 :       return parent_->routeStatsContext();
     909           0 :     }
     910           0 :     const UpgradeMap& upgradeMap() const override { return parent_->upgradeMap(); }
     911           0 :     const EarlyDataPolicy& earlyDataPolicy() const override { return parent_->earlyDataPolicy(); }
     912             : 
     913             :     // Router::Route
     914           0 :     const DirectResponseEntry* directResponseEntry() const override { return nullptr; }
     915          22 :     const RouteEntry* routeEntry() const override { return this; }
     916           0 :     const Decorator* decorator() const override { return parent_->decorator(); }
     917           0 :     const RouteTracing* tracingConfig() const override { return parent_->tracingConfig(); }
     918           0 :     absl::optional<bool> filterDisabled(absl::string_view config_name) const override {
     919           0 :       return parent_->filterDisabled(config_name);
     920           0 :     }
     921             :     const RouteSpecificFilterConfig*
     922           0 :     mostSpecificPerFilterConfig(const std::string& name) const override {
     923           0 :       return parent_->mostSpecificPerFilterConfig(name);
     924           0 :     }
     925             :     void traversePerFilterConfig(
     926             :         const std::string& filter_name,
     927           0 :         std::function<void(const Router::RouteSpecificFilterConfig&)> cb) const override {
     928           0 :       parent_->traversePerFilterConfig(filter_name, cb);
     929           0 :     };
     930           0 :     const std::string& routeName() const override { return parent_->routeName(); }
     931             : 
     932             :   private:
     933             :     const RouteEntryAndRoute* parent_;
     934             : 
     935             :     // If a DynamicRouteEntry instance is created and returned to the caller directly, then keep an
     936             :     // copy of the shared pointer to the parent Route (RouteEntryImplBase) to ensure the parent
     937             :     // is not destroyed before this entry.
     938             :     //
     939             :     // This should be nullptr if the DynamicRouteEntry is part of the parent (RouteEntryImplBase) to
     940             :     // avoid possible circular reference. For example, the WeightedClusterEntry (derived from
     941             :     // DynamicRouteEntry) will be member of the RouteEntryImplBase, so the owner_ should be nullptr.
     942             :     const RouteConstSharedPtr owner_;
     943             :     const std::string cluster_name_;
     944             :   };
     945             : 
     946             :   /**
     947             :    * Route entry implementation for weighted clusters. The RouteEntryImplBase object holds
     948             :    * one or more weighted cluster objects, where each object has a back pointer to the parent
     949             :    * RouteEntryImplBase object. Almost all functions in this class forward calls back to the
     950             :    * parent, with the exception of clusterName, routeEntry, and metadataMatchCriteria.
     951             :    */
     952             :   class WeightedClusterEntry : public DynamicRouteEntry {
     953             :   public:
     954             :     WeightedClusterEntry(const RouteEntryImplBase* parent, const std::string& rutime_key,
     955             :                          Server::Configuration::ServerFactoryContext& factory_context,
     956             :                          ProtobufMessage::ValidationVisitor& validator,
     957             :                          const envoy::config::route::v3::WeightedCluster::ClusterWeight& cluster);
     958             : 
     959         200 :     uint64_t clusterWeight() const {
     960         200 :       return loader_.snapshot().getInteger(runtime_key_, cluster_weight_);
     961         200 :     }
     962             : 
     963           0 :     const MetadataMatchCriteria* metadataMatchCriteria() const override {
     964           0 :       if (cluster_metadata_match_criteria_) {
     965           0 :         return cluster_metadata_match_criteria_.get();
     966           0 :       }
     967           0 :       return DynamicRouteEntry::metadataMatchCriteria();
     968           0 :     }
     969             : 
     970           2 :     const HeaderParser& requestHeaderParser() const {
     971           2 :       if (request_headers_parser_ != nullptr) {
     972           2 :         return *request_headers_parser_;
     973           2 :       }
     974           0 :       return HeaderParser::defaultParser();
     975           2 :     }
     976           0 :     const HeaderParser& responseHeaderParser() const {
     977           0 :       if (response_headers_parser_ != nullptr) {
     978           0 :         return *response_headers_parser_;
     979           0 :       }
     980           0 :       return HeaderParser::defaultParser();
     981           0 :     }
     982             : 
     983             :     void finalizeRequestHeaders(Http::RequestHeaderMap& headers,
     984             :                                 const StreamInfo::StreamInfo& stream_info,
     985           2 :                                 bool insert_envoy_original_path) const override {
     986           2 :       requestHeaderParser().evaluateHeaders(headers, stream_info);
     987           2 :       if (!host_rewrite_.empty()) {
     988           2 :         headers.setHost(host_rewrite_);
     989           2 :       }
     990           2 :       DynamicRouteEntry::finalizeRequestHeaders(headers, stream_info, insert_envoy_original_path);
     991           2 :     }
     992             :     Http::HeaderTransforms requestHeaderTransforms(const StreamInfo::StreamInfo& stream_info,
     993             :                                                    bool do_formatting = true) const override;
     994             :     void finalizeResponseHeaders(Http::ResponseHeaderMap& headers,
     995           0 :                                  const StreamInfo::StreamInfo& stream_info) const override {
     996           0 :       const Http::RequestHeaderMap& request_headers =
     997           0 :           stream_info.getRequestHeaders() == nullptr
     998           0 :               ? *Http::StaticEmptyHeaders::get().request_headers
     999           0 :               : *stream_info.getRequestHeaders();
    1000           0 :       responseHeaderParser().evaluateHeaders(headers, {&request_headers, &headers}, stream_info);
    1001           0 :       DynamicRouteEntry::finalizeResponseHeaders(headers, stream_info);
    1002           0 :     }
    1003             :     Http::HeaderTransforms responseHeaderTransforms(const StreamInfo::StreamInfo& stream_info,
    1004             :                                                     bool do_formatting = true) const override;
    1005             : 
    1006           0 :     absl::optional<bool> filterDisabled(absl::string_view config_name) const override {
    1007           0 :       absl::optional<bool> result = per_filter_configs_.disabled(config_name);
    1008           0 :       if (result.has_value()) {
    1009           0 :         return result.value();
    1010           0 :       }
    1011           0 :       return DynamicRouteEntry::filterDisabled(config_name);
    1012           0 :     }
    1013             :     const RouteSpecificFilterConfig*
    1014           0 :     mostSpecificPerFilterConfig(const std::string& name) const override {
    1015           0 :       auto* config = per_filter_configs_.get(name);
    1016           0 :       return config ? config : DynamicRouteEntry::mostSpecificPerFilterConfig(name);
    1017           0 :     }
    1018             : 
    1019             :     void traversePerFilterConfig(
    1020             :         const std::string& filter_name,
    1021             :         std::function<void(const Router::RouteSpecificFilterConfig&)> cb) const override;
    1022             : 
    1023          16 :     const Http::LowerCaseString& clusterHeaderName() const { return cluster_header_name_; }
    1024             : 
    1025             :   private:
    1026             :     const std::string runtime_key_;
    1027             :     Runtime::Loader& loader_;
    1028             :     const uint64_t cluster_weight_;
    1029             :     MetadataMatchCriteriaConstPtr cluster_metadata_match_criteria_;
    1030             :     HeaderParserPtr request_headers_parser_;
    1031             :     HeaderParserPtr response_headers_parser_;
    1032             :     PerFilterConfigs per_filter_configs_;
    1033             :     const std::string host_rewrite_;
    1034             :     const Http::LowerCaseString cluster_header_name_;
    1035             :   };
    1036             : 
    1037             :   using WeightedClusterEntrySharedPtr = std::shared_ptr<WeightedClusterEntry>;
    1038             :   // Container for route config elements that pertain to weighted clusters.
    1039             :   // We keep them in a separate data structure to avoid memory overhead for the routes that do not
    1040             :   // use weighted clusters.
    1041             :   struct WeightedClustersConfig {
    1042             :     WeightedClustersConfig(const std::vector<WeightedClusterEntrySharedPtr>&& weighted_clusters,
    1043             :                            uint64_t total_cluster_weight,
    1044             :                            const std::string& random_value_header_name)
    1045             :         : weighted_clusters_(std::move(weighted_clusters)),
    1046             :           total_cluster_weight_(total_cluster_weight),
    1047          86 :           random_value_header_name_(random_value_header_name) {}
    1048             :     const std::vector<WeightedClusterEntrySharedPtr> weighted_clusters_;
    1049             :     const uint64_t total_cluster_weight_;
    1050             :     const std::string random_value_header_name_;
    1051             :   };
    1052             : 
    1053             : protected:
    1054             :   const std::string prefix_rewrite_;
    1055             :   Regex::CompiledMatcherPtr regex_rewrite_;
    1056             :   const PathMatcherSharedPtr path_matcher_;
    1057             :   const PathRewriterSharedPtr path_rewriter_;
    1058             :   std::string regex_rewrite_substitution_;
    1059             :   const std::string host_rewrite_;
    1060             :   std::unique_ptr<ConnectConfig> connect_config_;
    1061             : 
    1062        1466 :   bool case_sensitive() const { return case_sensitive_; }
    1063             :   RouteConstSharedPtr clusterEntry(const Http::RequestHeaderMap& headers,
    1064             :                                    uint64_t random_value) const;
    1065             : 
    1066             :   /**
    1067             :    * Returns the correct path rewrite string for this route.
    1068             :    *
    1069             :    * The provided container may be used to store memory backing the return value
    1070             :    * therefore it must outlive any use of the return value.
    1071             :    */
    1072             :   const std::string& getPathRewrite(const Http::RequestHeaderMap& headers,
    1073             :                                     absl::optional<std::string>& container) const;
    1074             : 
    1075             :   void finalizePathHeader(Http::RequestHeaderMap& headers, absl::string_view matched_path,
    1076             :                           bool insert_envoy_original_path) const;
    1077             : 
    1078             :   absl::optional<std::string>
    1079             :   currentUrlPathAfterRewriteWithMatchedPath(const Http::RequestHeaderMap& headers,
    1080             :                                             absl::string_view matched_path) const;
    1081             : 
    1082             : private:
    1083             :   struct RuntimeData {
    1084             :     std::string fractional_runtime_key_{};
    1085             :     envoy::type::v3::FractionalPercent fractional_runtime_default_{};
    1086             :   };
    1087             : 
    1088             :   /**
    1089             :    * Returns a vector of request header parsers which applied or will apply header transformations
    1090             :    * to the request in this route.
    1091             :    * @param specificity_ascend specifies whether the returned parsers will be sorted from least
    1092             :    *        specific to most specific (global connection manager level header parser, virtual host
    1093             :    *        level header parser and finally route-level parser.) or the reverse.
    1094             :    * @return a vector of request header parsers.
    1095             :    */
    1096             :   absl::InlinedVector<const HeaderParser*, 3>
    1097             :   getRequestHeaderParsers(bool specificity_ascend) const;
    1098             : 
    1099             :   /**
    1100             :    * Returns a vector of response header parsers which applied or will apply header transformations
    1101             :    * to the response in this route.
    1102             :    * @param specificity_ascend specifies whether the returned parsers will be sorted from least
    1103             :    *        specific to most specific (global connection manager level header parser, virtual host
    1104             :    *        level header parser and finally route-level parser.) or the reverse.
    1105             :    * @return a vector of request header parsers.
    1106             :    */
    1107             :   absl::InlinedVector<const HeaderParser*, 3>
    1108             :   getResponseHeaderParsers(bool specificity_ascend) const;
    1109             : 
    1110             :   std::unique_ptr<const RuntimeData>
    1111             :   loadRuntimeData(const envoy::config::route::v3::RouteMatch& route);
    1112             : 
    1113             :   static std::multimap<std::string, std::string>
    1114             :   parseOpaqueConfig(const envoy::config::route::v3::Route& route);
    1115             : 
    1116             :   static DecoratorConstPtr parseDecorator(const envoy::config::route::v3::Route& route);
    1117             : 
    1118             :   static RouteTracingConstPtr parseRouteTracing(const envoy::config::route::v3::Route& route);
    1119             : 
    1120             :   bool evaluateRuntimeMatch(const uint64_t random_value) const;
    1121             : 
    1122             :   bool evaluateTlsContextMatch(const StreamInfo::StreamInfo& stream_info) const;
    1123             : 
    1124             :   std::unique_ptr<HedgePolicyImpl>
    1125             :   buildHedgePolicy(HedgePolicyConstOptRef vhost_hedge_policy,
    1126             :                    const envoy::config::route::v3::RouteAction& route_config) const;
    1127             : 
    1128             :   std::unique_ptr<RetryPolicyImpl>
    1129             :   buildRetryPolicy(RetryPolicyConstOptRef vhost_retry_policy,
    1130             :                    const envoy::config::route::v3::RouteAction& route_config,
    1131             :                    ProtobufMessage::ValidationVisitor& validation_visitor,
    1132             :                    Server::Configuration::ServerFactoryContext& factory_context) const;
    1133             : 
    1134             :   std::unique_ptr<InternalRedirectPolicyImpl>
    1135             :   buildInternalRedirectPolicy(const envoy::config::route::v3::RouteAction& route_config,
    1136             :                               ProtobufMessage::ValidationVisitor& validator,
    1137             :                               absl::string_view current_route_name) const;
    1138             : 
    1139             :   OptionalTimeouts buildOptionalTimeouts(const envoy::config::route::v3::RouteAction& route) const;
    1140             :   template <OptionalTimeoutNames timeout_name>
    1141         370 :   absl::optional<std::chrono::milliseconds> getOptionalTimeout() const {
    1142         370 :     const auto timeout = optional_timeouts_.get<timeout_name>();
    1143         370 :     if (timeout.has_value()) {
    1144           0 :       return *timeout;
    1145           0 :     }
    1146         370 :     return absl::nullopt;
    1147         370 :   }
    1148             : 
    1149             :   PathMatcherSharedPtr buildPathMatcher(envoy::config::route::v3::Route route,
    1150             :                                         ProtobufMessage::ValidationVisitor& validator) const;
    1151             : 
    1152             :   PathRewriterSharedPtr buildPathRewriter(envoy::config::route::v3::Route route,
    1153             :                                           ProtobufMessage::ValidationVisitor& validator) const;
    1154             : 
    1155             :   RouteConstSharedPtr
    1156             :   pickClusterViaClusterHeader(const Http::LowerCaseString& cluster_header_name,
    1157             :                               const Http::HeaderMap& headers,
    1158             :                               const RouteEntryAndRoute* route_selector_override) const;
    1159             : 
    1160             :   RouteConstSharedPtr pickWeightedCluster(const Http::HeaderMap& headers, uint64_t random_value,
    1161             :                                           bool ignore_overflow) const;
    1162             : 
    1163             :   // Default timeout is 15s if nothing is specified in the route config.
    1164             :   static const uint64_t DEFAULT_ROUTE_TIMEOUT_MS = 15000;
    1165             : 
    1166             :   std::unique_ptr<const CorsPolicyImpl> cors_policy_;
    1167             :   // Keep an copy of the shared pointer to the shared part of the virtual host. This is needed
    1168             :   // to keep the shared part alive while the route is alive.
    1169             :   const CommonVirtualHostSharedPtr vhost_;
    1170             :   const absl::optional<Http::LowerCaseString> auto_host_rewrite_header_;
    1171             :   const Regex::CompiledMatcherPtr host_rewrite_path_regex_;
    1172             :   const std::string host_rewrite_path_regex_substitution_;
    1173             :   const std::string cluster_name_;
    1174             :   RouteStatsContextPtr route_stats_context_;
    1175             :   const Http::LowerCaseString cluster_header_name_;
    1176             :   ClusterSpecifierPluginSharedPtr cluster_specifier_plugin_;
    1177             :   const std::chrono::milliseconds timeout_;
    1178             :   const OptionalTimeouts optional_timeouts_;
    1179             :   Runtime::Loader& loader_;
    1180             :   std::unique_ptr<const RuntimeData> runtime_;
    1181             :   std::unique_ptr<const ::Envoy::Http::Utility::RedirectConfig> redirect_config_;
    1182             :   std::unique_ptr<const HedgePolicyImpl> hedge_policy_;
    1183             :   std::unique_ptr<const RetryPolicyImpl> retry_policy_;
    1184             :   std::unique_ptr<const InternalRedirectPolicyImpl> internal_redirect_policy_;
    1185             :   std::unique_ptr<const RateLimitPolicyImpl> rate_limit_policy_;
    1186             :   std::vector<ShadowPolicyPtr> shadow_policies_;
    1187             :   std::vector<Http::HeaderUtility::HeaderDataPtr> config_headers_;
    1188             :   std::vector<ConfigUtility::QueryParameterMatcherPtr> config_query_parameters_;
    1189             :   std::unique_ptr<const WeightedClustersConfig> weighted_clusters_config_;
    1190             : 
    1191             :   UpgradeMap upgrade_map_;
    1192             :   std::unique_ptr<const Http::HashPolicyImpl> hash_policy_;
    1193             :   MetadataMatchCriteriaConstPtr metadata_match_criteria_;
    1194             :   TlsContextMatchCriteriaConstPtr tls_context_match_criteria_;
    1195             :   HeaderParserPtr request_headers_parser_;
    1196             :   HeaderParserPtr response_headers_parser_;
    1197             :   RouteMetadataPackPtr metadata_;
    1198             :   const std::vector<Envoy::Matchers::MetadataMatcher> dynamic_metadata_;
    1199             : 
    1200             :   // TODO(danielhochman): refactor multimap into unordered_map since JSON is unordered map.
    1201             :   const std::multimap<std::string, std::string> opaque_config_;
    1202             : 
    1203             :   const DecoratorConstPtr decorator_;
    1204             :   const RouteTracingConstPtr route_tracing_;
    1205             :   std::string direct_response_body_;
    1206             :   PerFilterConfigs per_filter_configs_;
    1207             :   const std::string route_name_;
    1208             :   TimeSource& time_source_;
    1209             :   EarlyDataPolicyPtr early_data_policy_;
    1210             : 
    1211             :   // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
    1212             :   uint32_t retry_shadow_buffer_limit_{std::numeric_limits<uint32_t>::max()};
    1213             :   const absl::optional<Http::Code> direct_response_code_;
    1214             :   const Http::Code cluster_not_found_response_code_;
    1215             :   const Upstream::ResourcePriority priority_;
    1216             :   const bool auto_host_rewrite_ : 1;
    1217             :   const bool append_xfh_ : 1;
    1218             :   const bool using_new_timeouts_ : 1;
    1219             :   const bool match_grpc_ : 1;
    1220             :   const bool case_sensitive_ : 1;
    1221             :   bool include_vh_rate_limits_ : 1;
    1222             : };
    1223             : 
    1224             : /**
    1225             :  * Route entry implementation for uri template match based routing.
    1226             :  */
    1227             : class UriTemplateMatcherRouteEntryImpl : public RouteEntryImplBase {
    1228             : public:
    1229             :   UriTemplateMatcherRouteEntryImpl(const CommonVirtualHostSharedPtr& vhost,
    1230             :                                    const envoy::config::route::v3::Route& route,
    1231             :                                    Server::Configuration::ServerFactoryContext& factory_context,
    1232             :                                    ProtobufMessage::ValidationVisitor& validator);
    1233             : 
    1234             :   // Router::PathMatchCriterion
    1235           0 :   const std::string& matcher() const override { return uri_template_; }
    1236           0 :   PathMatchType matchType() const override { return PathMatchType::Template; }
    1237             : 
    1238             :   // Router::Matchable
    1239             :   RouteConstSharedPtr matches(const Http::RequestHeaderMap& headers,
    1240             :                               const StreamInfo::StreamInfo& stream_info,
    1241             :                               uint64_t random_value) const override;
    1242             : 
    1243             :   // Router::DirectResponseEntry
    1244             :   void rewritePathHeader(Http::RequestHeaderMap& headers,
    1245             :                          bool insert_envoy_original_path) const override;
    1246             : 
    1247             :   // Router::RouteEntry
    1248             :   absl::optional<std::string>
    1249             :   currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const override;
    1250             : 
    1251             : private:
    1252             :   const std::string uri_template_;
    1253             : };
    1254             : 
    1255             : /**
    1256             :  * Route entry implementation for prefix path match routing.
    1257             :  */
    1258             : class PrefixRouteEntryImpl : public RouteEntryImplBase {
    1259             : public:
    1260             :   PrefixRouteEntryImpl(const CommonVirtualHostSharedPtr& vhost,
    1261             :                        const envoy::config::route::v3::Route& route,
    1262             :                        Server::Configuration::ServerFactoryContext& factory_context,
    1263             :                        ProtobufMessage::ValidationVisitor& validator);
    1264             : 
    1265             :   // Router::PathMatchCriterion
    1266         203 :   const std::string& matcher() const override {
    1267         203 :     return path_matcher_ != nullptr ? path_matcher_->matcher().matcher().prefix() : EMPTY_STRING;
    1268         203 :   }
    1269           0 :   PathMatchType matchType() const override { return PathMatchType::Prefix; }
    1270             : 
    1271             :   // Router::Matchable
    1272             :   RouteConstSharedPtr matches(const Http::RequestHeaderMap& headers,
    1273             :                               const StreamInfo::StreamInfo& stream_info,
    1274             :                               uint64_t random_value) const override;
    1275             : 
    1276             :   // Router::DirectResponseEntry
    1277             :   void rewritePathHeader(Http::RequestHeaderMap& headers,
    1278             :                          bool insert_envoy_original_path) const override;
    1279             : 
    1280             :   // Router::RouteEntry
    1281             :   absl::optional<std::string>
    1282             :   currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const override;
    1283             : 
    1284             : private:
    1285             :   const Matchers::PathMatcherConstSharedPtr path_matcher_;
    1286             : };
    1287             : 
    1288             : /**
    1289             :  * Route entry implementation for exact path match routing.
    1290             :  */
    1291             : class PathRouteEntryImpl : public RouteEntryImplBase {
    1292             : public:
    1293             :   PathRouteEntryImpl(const CommonVirtualHostSharedPtr& vhost,
    1294             :                      const envoy::config::route::v3::Route& route,
    1295             :                      Server::Configuration::ServerFactoryContext& factory_context,
    1296             :                      ProtobufMessage::ValidationVisitor& validator);
    1297             : 
    1298             :   // Router::PathMatchCriterion
    1299           0 :   const std::string& matcher() const override {
    1300           0 :     return path_matcher_ != nullptr ? path_matcher_->matcher().matcher().exact() : EMPTY_STRING;
    1301           0 :   }
    1302           0 :   PathMatchType matchType() const override { return PathMatchType::Exact; }
    1303             : 
    1304             :   // Router::Matchable
    1305             :   RouteConstSharedPtr matches(const Http::RequestHeaderMap& headers,
    1306             :                               const StreamInfo::StreamInfo& stream_info,
    1307             :                               uint64_t random_value) const override;
    1308             : 
    1309             :   // Router::DirectResponseEntry
    1310             :   void rewritePathHeader(Http::RequestHeaderMap& headers,
    1311             :                          bool insert_envoy_original_path) const override;
    1312             : 
    1313             :   // Router::RouteEntry
    1314             :   absl::optional<std::string>
    1315             :   currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const override;
    1316             : 
    1317             : private:
    1318             :   const Matchers::PathMatcherConstSharedPtr path_matcher_;
    1319             : };
    1320             : 
    1321             : /**
    1322             :  * Route entry implementation for regular expression match routing.
    1323             :  */
    1324             : class RegexRouteEntryImpl : public RouteEntryImplBase {
    1325             : public:
    1326             :   RegexRouteEntryImpl(const CommonVirtualHostSharedPtr& vhost,
    1327             :                       const envoy::config::route::v3::Route& route,
    1328             :                       Server::Configuration::ServerFactoryContext& factory_context,
    1329             :                       ProtobufMessage::ValidationVisitor& validator);
    1330             : 
    1331             :   // Router::PathMatchCriterion
    1332           0 :   const std::string& matcher() const override {
    1333           0 :     return path_matcher_ != nullptr ? path_matcher_->matcher().matcher().safe_regex().regex()
    1334           0 :                                     : EMPTY_STRING;
    1335           0 :   }
    1336           0 :   PathMatchType matchType() const override { return PathMatchType::Regex; }
    1337             : 
    1338             :   // Router::Matchable
    1339             :   RouteConstSharedPtr matches(const Http::RequestHeaderMap& headers,
    1340             :                               const StreamInfo::StreamInfo& stream_info,
    1341             :                               uint64_t random_value) const override;
    1342             : 
    1343             :   // Router::DirectResponseEntry
    1344             :   void rewritePathHeader(Http::RequestHeaderMap& headers,
    1345             :                          bool insert_envoy_original_path) const override;
    1346             : 
    1347             :   // Router::RouteEntry
    1348             :   absl::optional<std::string>
    1349             :   currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const override;
    1350             : 
    1351             : private:
    1352             :   const Matchers::PathMatcherConstSharedPtr path_matcher_;
    1353             : };
    1354             : 
    1355             : /**
    1356             :  * Route entry implementation for CONNECT requests.
    1357             :  */
    1358             : class ConnectRouteEntryImpl : public RouteEntryImplBase {
    1359             : public:
    1360             :   ConnectRouteEntryImpl(const CommonVirtualHostSharedPtr& vhost,
    1361             :                         const envoy::config::route::v3::Route& route,
    1362             :                         Server::Configuration::ServerFactoryContext& factory_context,
    1363             :                         ProtobufMessage::ValidationVisitor& validator);
    1364             : 
    1365             :   // Router::PathMatchCriterion
    1366           0 :   const std::string& matcher() const override { return EMPTY_STRING; }
    1367           0 :   PathMatchType matchType() const override { return PathMatchType::None; }
    1368             : 
    1369             :   // Router::Matchable
    1370             :   RouteConstSharedPtr matches(const Http::RequestHeaderMap& headers,
    1371             :                               const StreamInfo::StreamInfo& stream_info,
    1372             :                               uint64_t random_value) const override;
    1373             : 
    1374             :   // Router::DirectResponseEntry
    1375             :   void rewritePathHeader(Http::RequestHeaderMap&, bool) const override;
    1376             : 
    1377             :   // Router::RouteEntry
    1378             :   absl::optional<std::string>
    1379             :   currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const override;
    1380             : 
    1381           0 :   bool supportsPathlessHeaders() const override { return true; }
    1382             : };
    1383             : 
    1384             : /**
    1385             :  * Route entry implementation for path separated prefix match routing.
    1386             :  */
    1387             : class PathSeparatedPrefixRouteEntryImpl : public RouteEntryImplBase {
    1388             : public:
    1389             :   PathSeparatedPrefixRouteEntryImpl(const CommonVirtualHostSharedPtr& vhost,
    1390             :                                     const envoy::config::route::v3::Route& route,
    1391             :                                     Server::Configuration::ServerFactoryContext& factory_context,
    1392             :                                     ProtobufMessage::ValidationVisitor& validator);
    1393             : 
    1394             :   // Router::PathMatchCriterion
    1395           0 :   const std::string& matcher() const override {
    1396           0 :     return path_matcher_ != nullptr ? path_matcher_->matcher().matcher().prefix() : EMPTY_STRING;
    1397           0 :   }
    1398           0 :   PathMatchType matchType() const override { return PathMatchType::PathSeparatedPrefix; }
    1399             : 
    1400             :   // Router::Matchable
    1401             :   RouteConstSharedPtr matches(const Http::RequestHeaderMap& headers,
    1402             :                               const StreamInfo::StreamInfo& stream_info,
    1403             :                               uint64_t random_value) const override;
    1404             : 
    1405             :   // Router::DirectResponseEntry
    1406             :   void rewritePathHeader(Http::RequestHeaderMap& headers,
    1407             :                          bool insert_envoy_original_path) const override;
    1408             : 
    1409             :   // Router::RouteEntry
    1410             :   absl::optional<std::string>
    1411             :   currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const override;
    1412             : 
    1413             : private:
    1414             :   const Matchers::PathMatcherConstSharedPtr path_matcher_;
    1415             : };
    1416             : 
    1417             : // Contextual information used to construct the route actions for a match tree.
    1418             : struct RouteActionContext {
    1419             :   const CommonVirtualHostSharedPtr& vhost;
    1420             :   Server::Configuration::ServerFactoryContext& factory_context;
    1421             : };
    1422             : 
    1423             : // Action used with the matching tree to specify route to use for an incoming stream.
    1424             : class RouteMatchAction : public Matcher::ActionBase<envoy::config::route::v3::Route> {
    1425             : public:
    1426           2 :   explicit RouteMatchAction(RouteEntryImplBaseConstSharedPtr route) : route_(std::move(route)) {}
    1427             : 
    1428           2 :   RouteEntryImplBaseConstSharedPtr route() const { return route_; }
    1429             : 
    1430             : private:
    1431             :   const RouteEntryImplBaseConstSharedPtr route_;
    1432             : };
    1433             : 
    1434             : // Registered factory for RouteMatchAction.
    1435             : class RouteMatchActionFactory : public Matcher::ActionFactory<RouteActionContext> {
    1436             : public:
    1437             :   Matcher::ActionFactoryCb
    1438             :   createActionFactoryCb(const Protobuf::Message& config, RouteActionContext& context,
    1439             :                         ProtobufMessage::ValidationVisitor& validation_visitor) override;
    1440         190 :   std::string name() const override { return "route"; }
    1441          16 :   ProtobufTypes::MessagePtr createEmptyConfigProto() override {
    1442          16 :     return std::make_unique<envoy::config::route::v3::Route>();
    1443          16 :   }
    1444             : };
    1445             : 
    1446             : DECLARE_FACTORY(RouteMatchActionFactory);
    1447             : 
    1448             : // Similar to RouteMatchAction, but accepts v3::RouteList instead of v3::Route.
    1449             : class RouteListMatchAction : public Matcher::ActionBase<envoy::config::route::v3::RouteList> {
    1450             : public:
    1451             :   explicit RouteListMatchAction(std::vector<RouteEntryImplBaseConstSharedPtr> routes)
    1452           0 :       : routes_(std::move(routes)) {}
    1453             : 
    1454           0 :   const std::vector<RouteEntryImplBaseConstSharedPtr>& routes() const { return routes_; }
    1455             : 
    1456             : private:
    1457             :   const std::vector<RouteEntryImplBaseConstSharedPtr> routes_;
    1458             : };
    1459             : 
    1460             : // Registered factory for RouteListMatchAction.
    1461             : class RouteListMatchActionFactory : public Matcher::ActionFactory<RouteActionContext> {
    1462             : public:
    1463             :   Matcher::ActionFactoryCb
    1464             :   createActionFactoryCb(const Protobuf::Message& config, RouteActionContext& context,
    1465             :                         ProtobufMessage::ValidationVisitor& validation_visitor) override;
    1466         190 :   std::string name() const override { return "route_match_action"; }
    1467          13 :   ProtobufTypes::MessagePtr createEmptyConfigProto() override {
    1468          13 :     return std::make_unique<envoy::config::route::v3::RouteList>();
    1469          13 :   }
    1470             : };
    1471             : 
    1472             : DECLARE_FACTORY(RouteListMatchActionFactory);
    1473             : 
    1474             : /**
    1475             :  * Wraps the route configuration which matches an incoming request headers to a backend cluster.
    1476             :  * This is split out mainly to help with unit testing.
    1477             :  */
    1478             : class RouteMatcher {
    1479             : public:
    1480             :   RouteMatcher(const envoy::config::route::v3::RouteConfiguration& config,
    1481             :                const CommonConfigSharedPtr& global_route_config,
    1482             :                Server::Configuration::ServerFactoryContext& factory_context,
    1483             :                ProtobufMessage::ValidationVisitor& validator, bool validate_clusters);
    1484             : 
    1485             :   RouteConstSharedPtr route(const RouteCallback& cb, const Http::RequestHeaderMap& headers,
    1486             :                             const StreamInfo::StreamInfo& stream_info, uint64_t random_value) const;
    1487             : 
    1488             :   const VirtualHostImpl* findVirtualHost(const Http::RequestHeaderMap& headers) const;
    1489             : 
    1490             : private:
    1491             :   using WildcardVirtualHosts =
    1492             :       std::map<int64_t, absl::node_hash_map<std::string, VirtualHostSharedPtr>, std::greater<>>;
    1493             :   using SubstringFunction = std::function<absl::string_view(absl::string_view, int)>;
    1494             :   const VirtualHostImpl* findWildcardVirtualHost(absl::string_view host,
    1495             :                                                  const WildcardVirtualHosts& wildcard_virtual_hosts,
    1496             :                                                  SubstringFunction substring_function) const;
    1497          79 :   bool ignorePortInHostMatching() const { return ignore_port_in_host_matching_; }
    1498             : 
    1499             :   Stats::ScopeSharedPtr vhost_scope_;
    1500             :   absl::node_hash_map<std::string, VirtualHostSharedPtr> virtual_hosts_;
    1501             :   // std::greater as a minor optimization to iterate from more to less specific
    1502             :   //
    1503             :   // A note on using an unordered_map versus a vector of (string, VirtualHostSharedPtr) pairs:
    1504             :   //
    1505             :   // Based on local benchmarks, each vector entry costs around 20ns for recall and (string)
    1506             :   // comparison with a fixed cost of about 25ns. For unordered_map, the empty map costs about 65ns
    1507             :   // and climbs to about 110ns once there are any entries.
    1508             :   //
    1509             :   // The break-even is 4 entries.
    1510             :   WildcardVirtualHosts wildcard_virtual_host_suffixes_;
    1511             :   WildcardVirtualHosts wildcard_virtual_host_prefixes_;
    1512             : 
    1513             :   VirtualHostSharedPtr default_virtual_host_;
    1514             :   const bool ignore_port_in_host_matching_{false};
    1515             : };
    1516             : 
    1517             : /**
    1518             :  * Shared part of the route configuration implementation.
    1519             :  */
    1520             : class CommonConfigImpl : public CommonConfig {
    1521             : public:
    1522             :   CommonConfigImpl(const envoy::config::route::v3::RouteConfiguration& config,
    1523             :                    Server::Configuration::ServerFactoryContext& factory_context,
    1524             :                    ProtobufMessage::ValidationVisitor& validator);
    1525             : 
    1526         196 :   const HeaderParser& requestHeaderParser() const {
    1527         196 :     if (request_headers_parser_ != nullptr) {
    1528           1 :       return *request_headers_parser_;
    1529           1 :     }
    1530         195 :     return HeaderParser::defaultParser();
    1531         196 :   }
    1532         335 :   const HeaderParser& responseHeaderParser() const {
    1533         335 :     if (response_headers_parser_ != nullptr) {
    1534         202 :       return *response_headers_parser_;
    1535         202 :     }
    1536         133 :     return HeaderParser::defaultParser();
    1537         335 :   }
    1538             : 
    1539          40 :   const RouteSpecificFilterConfig* perFilterConfig(const std::string& name) const {
    1540          40 :     return per_filter_configs_.get(name);
    1541          40 :   }
    1542         427 :   absl::optional<bool> filterDisabled(absl::string_view config_name) const {
    1543         427 :     return per_filter_configs_.disabled(config_name);
    1544         427 :   }
    1545             : 
    1546             :   // Router::CommonConfig
    1547         208 :   const std::list<Http::LowerCaseString>& internalOnlyHeaders() const override {
    1548         208 :     return internal_only_headers_;
    1549         208 :   }
    1550           0 :   const std::string& name() const override { return name_; }
    1551           0 :   bool usesVhds() const override { return uses_vhds_; }
    1552         531 :   bool mostSpecificHeaderMutationsWins() const override {
    1553         531 :     return most_specific_header_mutations_wins_;
    1554         531 :   }
    1555        1645 :   uint32_t maxDirectResponseBodySizeBytes() const override {
    1556        1645 :     return max_direct_response_body_size_bytes_;
    1557        1645 :   }
    1558        1254 :   const std::vector<ShadowPolicyPtr>& shadowPolicies() const { return shadow_policies_; }
    1559             :   ClusterSpecifierPluginSharedPtr clusterSpecifierPlugin(absl::string_view provider) const;
    1560         674 :   bool ignorePathParametersInPathMatching() const {
    1561         674 :     return ignore_path_parameters_in_path_matching_;
    1562         674 :   }
    1563             :   const envoy::config::core::v3::Metadata& metadata() const override;
    1564             :   const Envoy::Config::TypedMetadata& typedMetadata() const override;
    1565             : 
    1566             : private:
    1567             :   std::list<Http::LowerCaseString> internal_only_headers_;
    1568             :   HeaderParserPtr request_headers_parser_;
    1569             :   HeaderParserPtr response_headers_parser_;
    1570             :   const std::string name_;
    1571             :   Stats::SymbolTable& symbol_table_;
    1572             :   std::vector<ShadowPolicyPtr> shadow_policies_;
    1573             :   // Cluster specifier plugins/providers.
    1574             :   absl::flat_hash_map<std::string, ClusterSpecifierPluginSharedPtr> cluster_specifier_plugins_;
    1575             :   PerFilterConfigs per_filter_configs_;
    1576             :   RouteMetadataPackPtr metadata_;
    1577             :   // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
    1578             :   const uint32_t max_direct_response_body_size_bytes_;
    1579             :   const bool uses_vhds_ : 1;
    1580             :   const bool most_specific_header_mutations_wins_ : 1;
    1581             :   const bool ignore_path_parameters_in_path_matching_ : 1;
    1582             : };
    1583             : 
    1584             : /**
    1585             :  * Implementation of Config that reads from a proto file.
    1586             :  */
    1587             : class ConfigImpl : public Config {
    1588             : public:
    1589             :   ConfigImpl(const envoy::config::route::v3::RouteConfiguration& config,
    1590             :              Server::Configuration::ServerFactoryContext& factory_context,
    1591             :              ProtobufMessage::ValidationVisitor& validator, bool validate_clusters_default);
    1592             : 
    1593           0 :   bool virtualHostExists(const Http::RequestHeaderMap& headers) const {
    1594           0 :     return route_matcher_->findVirtualHost(headers) != nullptr;
    1595           0 :   }
    1596             : 
    1597             :   // Router::Config
    1598             :   RouteConstSharedPtr route(const Http::RequestHeaderMap& headers,
    1599             :                             const StreamInfo::StreamInfo& stream_info,
    1600          92 :                             uint64_t random_value) const override {
    1601          92 :     return route(nullptr, headers, stream_info, random_value);
    1602          92 :   }
    1603             :   RouteConstSharedPtr route(const RouteCallback& cb, const Http::RequestHeaderMap& headers,
    1604             :                             const StreamInfo::StreamInfo& stream_info,
    1605             :                             uint64_t random_value) const override;
    1606         208 :   const std::list<Http::LowerCaseString>& internalOnlyHeaders() const override {
    1607         208 :     return shared_config_->internalOnlyHeaders();
    1608         208 :   }
    1609           0 :   const std::string& name() const override { return shared_config_->name(); }
    1610           0 :   bool usesVhds() const override { return shared_config_->usesVhds(); }
    1611           0 :   bool mostSpecificHeaderMutationsWins() const override {
    1612           0 :     return shared_config_->mostSpecificHeaderMutationsWins();
    1613           0 :   }
    1614           0 :   uint32_t maxDirectResponseBodySizeBytes() const override {
    1615           0 :     return shared_config_->maxDirectResponseBodySizeBytes();
    1616           0 :   }
    1617           0 :   const std::vector<ShadowPolicyPtr>& shadowPolicies() const {
    1618           0 :     return shared_config_->shadowPolicies();
    1619           0 :   }
    1620           0 :   bool ignorePathParametersInPathMatching() const {
    1621           0 :     return shared_config_->ignorePathParametersInPathMatching();
    1622           0 :   }
    1623           0 :   const envoy::config::core::v3::Metadata& metadata() const override {
    1624           0 :     return shared_config_->metadata();
    1625           0 :   }
    1626           0 :   const Envoy::Config::TypedMetadata& typedMetadata() const override {
    1627           0 :     return shared_config_->typedMetadata();
    1628           0 :   }
    1629             : 
    1630             : private:
    1631             :   CommonConfigSharedPtr shared_config_;
    1632             :   std::unique_ptr<RouteMatcher> route_matcher_;
    1633             : };
    1634             : 
    1635             : /**
    1636             :  * Implementation of Config that is empty.
    1637             :  */
    1638             : class NullConfigImpl : public Config {
    1639             : public:
    1640             :   // Router::Config
    1641             :   RouteConstSharedPtr route(const Http::RequestHeaderMap&, const StreamInfo::StreamInfo&,
    1642           0 :                             uint64_t) const override {
    1643           0 :     return nullptr;
    1644           0 :   }
    1645             : 
    1646             :   RouteConstSharedPtr route(const RouteCallback&, const Http::RequestHeaderMap&,
    1647          98 :                             const StreamInfo::StreamInfo&, uint64_t) const override {
    1648          98 :     return nullptr;
    1649          98 :   }
    1650             : 
    1651          98 :   const std::list<Http::LowerCaseString>& internalOnlyHeaders() const override {
    1652          98 :     return internal_only_headers_;
    1653          98 :   }
    1654             : 
    1655           0 :   const std::string& name() const override { return name_; }
    1656           0 :   bool usesVhds() const override { return false; }
    1657           0 :   bool mostSpecificHeaderMutationsWins() const override { return false; }
    1658           0 :   uint32_t maxDirectResponseBodySizeBytes() const override { return 0; }
    1659             :   const envoy::config::core::v3::Metadata& metadata() const override;
    1660             :   const Envoy::Config::TypedMetadata& typedMetadata() const override;
    1661             : 
    1662             : private:
    1663             :   std::list<Http::LowerCaseString> internal_only_headers_;
    1664             :   const std::string name_;
    1665             : };
    1666             : 
    1667             : } // namespace Router
    1668             : } // namespace Envoy

Generated by: LCOV version 1.15