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