/proc/self/cwd/source/extensions/filters/network/http_connection_manager/config.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/extensions/filters/network/http_connection_manager/config.h" |
2 | | |
3 | | #include <chrono> |
4 | | #include <memory> |
5 | | #include <string> |
6 | | #include <vector> |
7 | | |
8 | | #include "envoy/config/core/v3/base.pb.h" |
9 | | #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h" |
10 | | #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.validate.h" |
11 | | #include "envoy/extensions/http/header_validators/envoy_default/v3/header_validator.pb.h" |
12 | | #include "envoy/extensions/http/original_ip_detection/xff/v3/xff.pb.h" |
13 | | #include "envoy/extensions/request_id/uuid/v3/uuid.pb.h" |
14 | | #include "envoy/filesystem/filesystem.h" |
15 | | #include "envoy/http/header_validator_factory.h" |
16 | | #include "envoy/registry/registry.h" |
17 | | #include "envoy/server/admin.h" |
18 | | #include "envoy/tracing/tracer.h" |
19 | | #include "envoy/type/tracing/v3/custom_tag.pb.h" |
20 | | #include "envoy/type/v3/percent.pb.h" |
21 | | |
22 | | #include "source/common/access_log/access_log_impl.h" |
23 | | #include "source/common/common/fmt.h" |
24 | | #include "source/common/config/utility.h" |
25 | | #include "source/common/http/conn_manager_config.h" |
26 | | #include "source/common/http/conn_manager_utility.h" |
27 | | #include "source/common/http/default_server_string.h" |
28 | | #include "source/common/http/http1/codec_impl.h" |
29 | | #include "source/common/http/http1/settings.h" |
30 | | #include "source/common/http/http2/codec_impl.h" |
31 | | #include "source/common/http/request_id_extension_impl.h" |
32 | | #include "source/common/http/utility.h" |
33 | | #include "source/common/local_reply/local_reply.h" |
34 | | #include "source/common/protobuf/utility.h" |
35 | | #include "source/common/quic/server_connection_factory.h" |
36 | | #include "source/common/router/rds_impl.h" |
37 | | #include "source/common/router/scoped_rds.h" |
38 | | #include "source/common/runtime/runtime_impl.h" |
39 | | #include "source/common/tracing/custom_tag_impl.h" |
40 | | #include "source/common/tracing/tracer_config_impl.h" |
41 | | #include "source/common/tracing/tracer_manager_impl.h" |
42 | | |
43 | | namespace Envoy { |
44 | | namespace Extensions { |
45 | | namespace NetworkFilters { |
46 | | namespace HttpConnectionManager { |
47 | | namespace { |
48 | | |
49 | | using FilterFactoriesList = std::list<Http::FilterFactoryCb>; |
50 | | using FilterFactoryMap = std::map<std::string, HttpConnectionManagerConfig::FilterConfig>; |
51 | | |
52 | | HttpConnectionManagerConfig::UpgradeMap::const_iterator |
53 | | findUpgradeBoolCaseInsensitive(const HttpConnectionManagerConfig::UpgradeMap& upgrade_map, |
54 | 0 | absl::string_view upgrade_type) { |
55 | 0 | for (auto it = upgrade_map.begin(); it != upgrade_map.end(); ++it) { |
56 | 0 | if (StringUtil::CaseInsensitiveCompare()(it->first, upgrade_type)) { |
57 | 0 | return it; |
58 | 0 | } |
59 | 0 | } |
60 | 0 | return upgrade_map.end(); |
61 | 0 | } |
62 | | |
63 | | FilterFactoryMap::const_iterator findUpgradeCaseInsensitive(const FilterFactoryMap& upgrade_map, |
64 | 1.26k | absl::string_view upgrade_type) { |
65 | 3.08k | for (auto it = upgrade_map.begin(); it != upgrade_map.end(); ++it) { |
66 | 1.91k | if (StringUtil::CaseInsensitiveCompare()(it->first, upgrade_type)) { |
67 | 92 | return it; |
68 | 92 | } |
69 | 1.91k | } |
70 | 1.16k | return upgrade_map.end(); |
71 | 1.26k | } |
72 | | |
73 | | std::unique_ptr<Http::InternalAddressConfig> createInternalAddressConfig( |
74 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
75 | 6.61k | config) { |
76 | 6.61k | if (config.has_internal_address_config()) { |
77 | 766 | return std::make_unique<InternalAddressConfig>(config.internal_address_config()); |
78 | 766 | } |
79 | | |
80 | 5.84k | return std::make_unique<Http::DefaultInternalAddressConfig>(); |
81 | 6.61k | } |
82 | | |
83 | | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
84 | | PathWithEscapedSlashesAction |
85 | 2.71k | getPathWithEscapedSlashesActionRuntimeOverride(Server::Configuration::FactoryContext& context) { |
86 | | // The default behavior is to leave escaped slashes unchanged. |
87 | 2.71k | uint64_t runtime_override = context.runtime().snapshot().getInteger( |
88 | 2.71k | "http_connection_manager.path_with_escaped_slashes_action", 0); |
89 | 2.71k | switch (runtime_override) { |
90 | 2.71k | default: |
91 | | // Also includes runtime override values of 0 and 1 |
92 | 2.71k | return envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
93 | 2.71k | KEEP_UNCHANGED; |
94 | 0 | case 2: |
95 | 0 | return envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
96 | 0 | REJECT_REQUEST; |
97 | 0 | case 3: |
98 | 0 | return envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
99 | 0 | UNESCAPE_AND_REDIRECT; |
100 | 0 | case 4: |
101 | 0 | return envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
102 | 0 | UNESCAPE_AND_FORWARD; |
103 | 2.71k | } |
104 | 2.71k | } |
105 | | |
106 | | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
107 | | PathWithEscapedSlashesAction |
108 | | getPathWithEscapedSlashesAction(const envoy::extensions::filters::network:: |
109 | | http_connection_manager::v3::HttpConnectionManager& config, |
110 | 6.24k | Server::Configuration::FactoryContext& context) { |
111 | 6.24k | envoy::type::v3::FractionalPercent default_fraction; |
112 | 6.24k | default_fraction.set_numerator(100); |
113 | 6.24k | default_fraction.set_denominator(envoy::type::v3::FractionalPercent::HUNDRED); |
114 | 6.24k | if (context.runtime().snapshot().featureEnabled( |
115 | 6.24k | "http_connection_manager.path_with_escaped_slashes_action_enabled", default_fraction)) { |
116 | 2.71k | return config.path_with_escaped_slashes_action() == |
117 | 2.71k | envoy::extensions::filters::network::http_connection_manager::v3:: |
118 | 2.71k | HttpConnectionManager::IMPLEMENTATION_SPECIFIC_DEFAULT |
119 | 2.71k | ? getPathWithEscapedSlashesActionRuntimeOverride(context) |
120 | 2.71k | : config.path_with_escaped_slashes_action(); |
121 | 2.71k | } |
122 | | |
123 | | // When action is disabled through runtime the behavior is to keep escaped slashes unchanged. |
124 | 3.53k | return envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
125 | 3.53k | KEEP_UNCHANGED; |
126 | 6.24k | } |
127 | | |
128 | | Http::HeaderValidatorFactoryPtr |
129 | | createHeaderValidatorFactory([[maybe_unused]] const envoy::extensions::filters::network:: |
130 | | http_connection_manager::v3::HttpConnectionManager& config, |
131 | 6.24k | [[maybe_unused]] Server::Configuration::FactoryContext& context) { |
132 | | |
133 | 6.24k | Http::HeaderValidatorFactoryPtr header_validator_factory; |
134 | | #ifdef ENVOY_ENABLE_UHV |
135 | | if (!Runtime::runtimeFeatureEnabled( |
136 | | "envoy.reloadable_features.enable_universal_header_validator")) { |
137 | | // This will cause codecs to use legacy header validation and path normalization |
138 | | return nullptr; |
139 | | } |
140 | | ::envoy::config::core::v3::TypedExtensionConfig legacy_header_validator_config; |
141 | | if (!config.has_typed_header_validation_config()) { |
142 | | // If header validator is not configured ensure that the defaults match Envoy's original |
143 | | // behavior. |
144 | | ::envoy::extensions::http::header_validators::envoy_default::v3::HeaderValidatorConfig |
145 | | uhv_config; |
146 | | // By default legacy config had path normalization and merge slashes disabled. |
147 | | uhv_config.mutable_uri_path_normalization_options()->set_skip_path_normalization( |
148 | | !config.has_normalize_path() || !config.normalize_path().value()); |
149 | | uhv_config.mutable_uri_path_normalization_options()->set_skip_merging_slashes( |
150 | | !config.merge_slashes()); |
151 | | uhv_config.mutable_uri_path_normalization_options()->set_path_with_escaped_slashes_action( |
152 | | static_cast< |
153 | | ::envoy::extensions::http::header_validators::envoy_default::v3::HeaderValidatorConfig:: |
154 | | UriPathNormalizationOptions::PathWithEscapedSlashesAction>( |
155 | | getPathWithEscapedSlashesAction(config, context))); |
156 | | uhv_config.mutable_http1_protocol_options()->set_allow_chunked_length( |
157 | | config.http_protocol_options().allow_chunked_length()); |
158 | | uhv_config.set_headers_with_underscores_action( |
159 | | static_cast<::envoy::extensions::http::header_validators::envoy_default::v3:: |
160 | | HeaderValidatorConfig::HeadersWithUnderscoresAction>( |
161 | | config.common_http_protocol_options().headers_with_underscores_action())); |
162 | | uhv_config.set_strip_fragment_from_path(!Runtime::runtimeFeatureEnabled( |
163 | | "envoy.reloadable_features.http_reject_path_with_fragment")); |
164 | | legacy_header_validator_config.set_name("default_envoy_uhv_from_legacy_settings"); |
165 | | legacy_header_validator_config.mutable_typed_config()->PackFrom(uhv_config); |
166 | | } |
167 | | |
168 | | const ::envoy::config::core::v3::TypedExtensionConfig& header_validator_config = |
169 | | config.has_typed_header_validation_config() ? config.typed_header_validation_config() |
170 | | : legacy_header_validator_config; |
171 | | |
172 | | auto* factory = Envoy::Config::Utility::getFactory<Http::HeaderValidatorFactoryConfig>( |
173 | | header_validator_config); |
174 | | if (!factory) { |
175 | | throwEnvoyExceptionOrPanic( |
176 | | fmt::format("Header validator extension not found: '{}'", header_validator_config.name())); |
177 | | } |
178 | | |
179 | | header_validator_factory = factory->createFromProto(header_validator_config.typed_config(), |
180 | | context.getServerFactoryContext()); |
181 | | if (!header_validator_factory) { |
182 | | throwEnvoyExceptionOrPanic(fmt::format("Header validator extension could not be created: '{}'", |
183 | | header_validator_config.name())); |
184 | | } |
185 | | #else |
186 | 6.24k | if (config.has_typed_header_validation_config()) { |
187 | 7 | throwEnvoyExceptionOrPanic( |
188 | 7 | fmt::format("This Envoy binary does not support header validator extensions.: '{}'", |
189 | 7 | config.typed_header_validation_config().name())); |
190 | 7 | } |
191 | | |
192 | 6.23k | if (Runtime::runtimeFeatureEnabled( |
193 | 6.23k | "envoy.reloadable_features.enable_universal_header_validator")) { |
194 | 0 | throwEnvoyExceptionOrPanic( |
195 | 0 | "Header validator can not be enabled since this Envoy binary does not support it."); |
196 | 0 | } |
197 | 6.23k | #endif |
198 | 6.23k | return header_validator_factory; |
199 | 6.23k | } |
200 | | |
201 | | } // namespace |
202 | | |
203 | | // Singleton registration via macro defined in envoy/singleton/manager.h |
204 | | SINGLETON_MANAGER_REGISTRATION(date_provider); |
205 | | SINGLETON_MANAGER_REGISTRATION(route_config_provider_manager); |
206 | | SINGLETON_MANAGER_REGISTRATION(scoped_routes_config_provider_manager); |
207 | | |
208 | 6.61k | Utility::Singletons Utility::createSingletons(Server::Configuration::FactoryContext& context) { |
209 | 6.61k | std::shared_ptr<Http::TlsCachingDateProviderImpl> date_provider = |
210 | 6.61k | context.singletonManager().getTyped<Http::TlsCachingDateProviderImpl>( |
211 | 6.61k | SINGLETON_MANAGER_REGISTERED_NAME(date_provider), [&context] { |
212 | 5.35k | return std::make_shared<Http::TlsCachingDateProviderImpl>( |
213 | 5.35k | context.mainThreadDispatcher(), context.threadLocal()); |
214 | 5.35k | }); |
215 | | |
216 | 6.61k | Router::RouteConfigProviderManagerSharedPtr route_config_provider_manager = |
217 | 6.61k | context.singletonManager().getTyped<Router::RouteConfigProviderManager>( |
218 | 6.61k | SINGLETON_MANAGER_REGISTERED_NAME(route_config_provider_manager), [&context] { |
219 | 5.35k | return std::make_shared<Router::RouteConfigProviderManagerImpl>(context.admin()); |
220 | 5.35k | }); |
221 | | |
222 | 6.61k | Router::ScopedRoutesConfigProviderManagerSharedPtr scoped_routes_config_provider_manager = |
223 | 6.61k | context.singletonManager().getTyped<Router::ScopedRoutesConfigProviderManager>( |
224 | 6.61k | SINGLETON_MANAGER_REGISTERED_NAME(scoped_routes_config_provider_manager), |
225 | 6.61k | [&context, route_config_provider_manager] { |
226 | 5.35k | return std::make_shared<Router::ScopedRoutesConfigProviderManager>( |
227 | 5.35k | context.admin(), *route_config_provider_manager); |
228 | 5.35k | }); |
229 | | |
230 | 6.61k | auto tracer_manager = Tracing::TracerManagerImpl::singleton(context); |
231 | | |
232 | 6.61k | std::shared_ptr<Http::DownstreamFilterConfigProviderManager> filter_config_provider_manager = |
233 | 6.61k | Http::FilterChainUtility::createSingletonDownstreamFilterConfigProviderManager( |
234 | 6.61k | context.getServerFactoryContext()); |
235 | | |
236 | 6.61k | return {date_provider, route_config_provider_manager, scoped_routes_config_provider_manager, |
237 | 6.61k | tracer_manager, filter_config_provider_manager}; |
238 | 6.61k | } |
239 | | |
240 | | std::shared_ptr<HttpConnectionManagerConfig> Utility::createConfig( |
241 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
242 | | proto_config, |
243 | | Server::Configuration::FactoryContext& context, Http::DateProvider& date_provider, |
244 | | Router::RouteConfigProviderManager& route_config_provider_manager, |
245 | | Config::ConfigProviderManager& scoped_routes_config_provider_manager, |
246 | | Tracing::TracerManager& tracer_manager, |
247 | 6.61k | FilterConfigProviderManager& filter_config_provider_manager) { |
248 | 6.61k | return std::make_shared<HttpConnectionManagerConfig>( |
249 | 6.61k | proto_config, context, date_provider, route_config_provider_manager, |
250 | 6.61k | scoped_routes_config_provider_manager, tracer_manager, filter_config_provider_manager); |
251 | 6.61k | } |
252 | | |
253 | | Network::FilterFactoryCb |
254 | | HttpConnectionManagerFilterConfigFactory::createFilterFactoryFromProtoTyped( |
255 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
256 | | proto_config, |
257 | 6.61k | Server::Configuration::FactoryContext& context) { |
258 | 6.61k | return createFilterFactoryFromProtoAndHopByHop(proto_config, context, true); |
259 | 6.61k | } |
260 | | |
261 | | Network::FilterFactoryCb |
262 | | HttpConnectionManagerFilterConfigFactory::createFilterFactoryFromProtoAndHopByHop( |
263 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
264 | | proto_config, |
265 | 6.61k | Server::Configuration::FactoryContext& context, bool clear_hop_by_hop_headers) { |
266 | 6.61k | Utility::Singletons singletons = Utility::createSingletons(context); |
267 | | |
268 | 6.61k | auto filter_config = Utility::createConfig( |
269 | 6.61k | proto_config, context, *singletons.date_provider_, *singletons.route_config_provider_manager_, |
270 | 6.61k | *singletons.scoped_routes_config_provider_manager_, *singletons.tracer_manager_, |
271 | 6.61k | *singletons.filter_config_provider_manager_); |
272 | | |
273 | | // This lambda captures the shared_ptrs created above, thus preserving the |
274 | | // reference count. |
275 | | // Keep in mind the lambda capture list **doesn't** determine the destruction order, but it's fine |
276 | | // as these captured objects are also global singletons. |
277 | 6.61k | return [singletons, filter_config, &context, |
278 | 6.61k | clear_hop_by_hop_headers](Network::FilterManager& filter_manager) -> void { |
279 | 4.97k | auto hcm = std::make_shared<Http::ConnectionManagerImpl>( |
280 | 4.97k | *filter_config, context.drainDecision(), context.api().randomGenerator(), |
281 | 4.97k | context.httpContext(), context.runtime(), context.localInfo(), context.clusterManager(), |
282 | 4.97k | context.overloadManager(), context.mainThreadDispatcher().timeSource()); |
283 | 4.97k | if (!clear_hop_by_hop_headers) { |
284 | 0 | hcm->setClearHopByHopResponseHeaders(false); |
285 | 0 | } |
286 | 4.97k | filter_manager.addReadFilter(std::move(hcm)); |
287 | 4.97k | }; |
288 | 6.61k | } |
289 | | |
290 | | Network::FilterFactoryCb |
291 | | MobileHttpConnectionManagerFilterConfigFactory::createFilterFactoryFromProtoTyped( |
292 | | const envoy::extensions::filters::network::http_connection_manager::v3:: |
293 | | EnvoyMobileHttpConnectionManager& mobile_config, |
294 | 0 | Server::Configuration::FactoryContext& context) { |
295 | 0 | return HttpConnectionManagerFilterConfigFactory::createFilterFactoryFromProtoAndHopByHop( |
296 | 0 | mobile_config.config(), context, false); |
297 | 0 | } |
298 | | |
299 | | /** |
300 | | * Static registration for the HTTP connection manager filter. |
301 | | */ |
302 | | LEGACY_REGISTER_FACTORY(HttpConnectionManagerFilterConfigFactory, |
303 | | Server::Configuration::NamedNetworkFilterConfigFactory, |
304 | | "envoy.http_connection_manager"); |
305 | | |
306 | | InternalAddressConfig::InternalAddressConfig( |
307 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
308 | | InternalAddressConfig& config) |
309 | 766 | : unix_sockets_(config.unix_sockets()), cidr_ranges_(config.cidr_ranges()) {} |
310 | | |
311 | | HttpConnectionManagerConfig::HttpConnectionManagerConfig( |
312 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
313 | | config, |
314 | | Server::Configuration::FactoryContext& context, Http::DateProvider& date_provider, |
315 | | Router::RouteConfigProviderManager& route_config_provider_manager, |
316 | | Config::ConfigProviderManager& scoped_routes_config_provider_manager, |
317 | | Tracing::TracerManager& tracer_manager, |
318 | | FilterConfigProviderManager& filter_config_provider_manager) |
319 | | : context_(context), stats_prefix_(fmt::format("http.{}.", config.stat_prefix())), |
320 | | stats_(Http::ConnectionManagerImpl::generateStats(stats_prefix_, context_.scope())), |
321 | | tracing_stats_( |
322 | | Http::ConnectionManagerImpl::generateTracingStats(stats_prefix_, context_.scope())), |
323 | | use_remote_address_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, use_remote_address, false)), |
324 | | internal_address_config_(createInternalAddressConfig(config)), |
325 | | xff_num_trusted_hops_(config.xff_num_trusted_hops()), |
326 | | skip_xff_append_(config.skip_xff_append()), via_(config.via()), |
327 | | route_config_provider_manager_(route_config_provider_manager), |
328 | | scoped_routes_config_provider_manager_(scoped_routes_config_provider_manager), |
329 | | filter_config_provider_manager_(filter_config_provider_manager), |
330 | | http3_options_(Http3::Utility::initializeAndValidateOptions( |
331 | | config.http3_protocol_options(), config.has_stream_error_on_invalid_http_message(), |
332 | | config.stream_error_on_invalid_http_message())), |
333 | | http2_options_(Http2::Utility::initializeAndValidateOptions( |
334 | | config.http2_protocol_options(), config.has_stream_error_on_invalid_http_message(), |
335 | | config.stream_error_on_invalid_http_message())), |
336 | | http1_settings_(Http::Http1::parseHttp1Settings( |
337 | | config.http_protocol_options(), context.messageValidationVisitor(), |
338 | | config.stream_error_on_invalid_http_message(), |
339 | | xff_num_trusted_hops_ == 0 && use_remote_address_)), |
340 | | max_request_headers_kb_(PROTOBUF_GET_WRAPPED_OR_DEFAULT( |
341 | | config, max_request_headers_kb, |
342 | | context.runtime().snapshot().getInteger(Http::MaxRequestHeadersSizeOverrideKey, |
343 | | Http::DEFAULT_MAX_REQUEST_HEADERS_KB))), |
344 | | max_request_headers_count_(PROTOBUF_GET_WRAPPED_OR_DEFAULT( |
345 | | config.common_http_protocol_options(), max_headers_count, |
346 | | context.runtime().snapshot().getInteger(Http::MaxRequestHeadersCountOverrideKey, |
347 | | Http::DEFAULT_MAX_HEADERS_COUNT))), |
348 | | idle_timeout_(PROTOBUF_GET_OPTIONAL_MS(config.common_http_protocol_options(), idle_timeout)), |
349 | | max_connection_duration_( |
350 | | PROTOBUF_GET_OPTIONAL_MS(config.common_http_protocol_options(), max_connection_duration)), |
351 | | max_stream_duration_( |
352 | | PROTOBUF_GET_OPTIONAL_MS(config.common_http_protocol_options(), max_stream_duration)), |
353 | | stream_idle_timeout_( |
354 | | PROTOBUF_GET_MS_OR_DEFAULT(config, stream_idle_timeout, StreamIdleTimeoutMs)), |
355 | | request_timeout_(PROTOBUF_GET_MS_OR_DEFAULT(config, request_timeout, RequestTimeoutMs)), |
356 | | request_headers_timeout_( |
357 | | PROTOBUF_GET_MS_OR_DEFAULT(config, request_headers_timeout, RequestHeaderTimeoutMs)), |
358 | | drain_timeout_(PROTOBUF_GET_MS_OR_DEFAULT(config, drain_timeout, 5000)), |
359 | | generate_request_id_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, generate_request_id, true)), |
360 | | preserve_external_request_id_(config.preserve_external_request_id()), |
361 | | always_set_request_id_in_response_(config.always_set_request_id_in_response()), |
362 | | date_provider_(date_provider), |
363 | | listener_stats_(Http::ConnectionManagerImpl::generateListenerStats(stats_prefix_, |
364 | | context_.listenerScope())), |
365 | | proxy_100_continue_(config.proxy_100_continue()), |
366 | | stream_error_on_invalid_http_messaging_( |
367 | | PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, stream_error_on_invalid_http_message, false)), |
368 | | delayed_close_timeout_(PROTOBUF_GET_MS_OR_DEFAULT(config, delayed_close_timeout, 1000)), |
369 | | #ifdef ENVOY_NORMALIZE_PATH_BY_DEFAULT |
370 | | normalize_path_(PROTOBUF_GET_WRAPPED_OR_DEFAULT( |
371 | | config, normalize_path, |
372 | | // TODO(htuch): we should have a boolean variant of featureEnabled() here. |
373 | | context.runtime().snapshot().featureEnabled("http_connection_manager.normalize_path", |
374 | | 100))), |
375 | | #else |
376 | | normalize_path_(PROTOBUF_GET_WRAPPED_OR_DEFAULT( |
377 | | config, normalize_path, |
378 | | // TODO(htuch): we should have a boolean variant of featureEnabled() here. |
379 | | context.runtime().snapshot().featureEnabled("http_connection_manager.normalize_path", |
380 | | 0))), |
381 | | #endif |
382 | | merge_slashes_(config.merge_slashes()), |
383 | | headers_with_underscores_action_( |
384 | | config.common_http_protocol_options().headers_with_underscores_action()), |
385 | | local_reply_(LocalReply::Factory::create(config.local_reply_config(), context)), |
386 | | path_with_escaped_slashes_action_(getPathWithEscapedSlashesAction(config, context)), |
387 | | strip_trailing_host_dot_(config.strip_trailing_host_dot()), |
388 | | max_requests_per_connection_(PROTOBUF_GET_WRAPPED_OR_DEFAULT( |
389 | | config.common_http_protocol_options(), max_requests_per_connection, 0)), |
390 | | proxy_status_config_(config.has_proxy_status_config() |
391 | | ? std::make_unique<HttpConnectionManagerProto::ProxyStatusConfig>( |
392 | | config.proxy_status_config()) |
393 | | : nullptr), |
394 | | header_validator_factory_(createHeaderValidatorFactory(config, context)), |
395 | | append_x_forwarded_port_(config.append_x_forwarded_port()), |
396 | | add_proxy_protocol_connection_state_( |
397 | 6.61k | PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, add_proxy_protocol_connection_state, true)) { |
398 | 6.61k | if (!idle_timeout_) { |
399 | 5.88k | idle_timeout_ = std::chrono::hours(1); |
400 | 5.88k | } else if (idle_timeout_.value().count() == 0) { |
401 | 207 | idle_timeout_ = absl::nullopt; |
402 | 207 | } |
403 | | |
404 | 6.61k | if (config.strip_any_host_port() && config.strip_matching_host_port()) { |
405 | 15 | throwEnvoyExceptionOrPanic(fmt::format( |
406 | 15 | "Error: Only one of `strip_matching_host_port` or `strip_any_host_port` can be set.")); |
407 | 15 | } |
408 | | |
409 | 6.59k | if (config.strip_any_host_port()) { |
410 | 700 | strip_port_type_ = Http::StripPortType::Any; |
411 | 5.89k | } else if (config.strip_matching_host_port()) { |
412 | 497 | strip_port_type_ = Http::StripPortType::MatchingHost; |
413 | 5.40k | } else { |
414 | 5.40k | strip_port_type_ = Http::StripPortType::None; |
415 | 5.40k | } |
416 | | |
417 | | // If we are provided a different request_id_extension implementation to use try and create a |
418 | | // new instance of it, otherwise use default one. |
419 | 6.59k | envoy::extensions::filters::network::http_connection_manager::v3::RequestIDExtension |
420 | 6.59k | final_rid_config = config.request_id_extension(); |
421 | 6.59k | if (!final_rid_config.has_typed_config()) { |
422 | | // This creates a default version of the UUID extension which is a required extension in the |
423 | | // build. |
424 | 6.14k | final_rid_config.mutable_typed_config()->PackFrom( |
425 | 6.14k | envoy::extensions::request_id::uuid::v3::UuidRequestIdConfig()); |
426 | 6.14k | } |
427 | 6.59k | auto extension_or_error = Http::RequestIDExtensionFactory::fromProto(final_rid_config, context_); |
428 | 6.59k | THROW_IF_STATUS_NOT_OK(extension_or_error, throw); |
429 | 6.51k | request_id_extension_ = extension_or_error.value(); |
430 | | |
431 | | // Check if IP detection extensions were configured, otherwise fall back to XFF. |
432 | 6.51k | auto ip_detection_extensions = config.original_ip_detection_extensions(); |
433 | 6.51k | if (ip_detection_extensions.empty()) { |
434 | 6.11k | envoy::extensions::http::original_ip_detection::xff::v3::XffConfig xff_config; |
435 | 6.11k | xff_config.set_xff_num_trusted_hops(xff_num_trusted_hops_); |
436 | | |
437 | 6.11k | auto* extension = ip_detection_extensions.Add(); |
438 | 6.11k | extension->set_name("envoy.http.original_ip_detection.xff"); |
439 | 6.11k | extension->mutable_typed_config()->PackFrom(xff_config); |
440 | 6.11k | } else { |
441 | 400 | if (use_remote_address_) { |
442 | 2 | throwEnvoyExceptionOrPanic( |
443 | 2 | "Original IP detection extensions and use_remote_address may not be mixed"); |
444 | 2 | } |
445 | | |
446 | 398 | if (xff_num_trusted_hops_ > 0) { |
447 | 6 | throwEnvoyExceptionOrPanic( |
448 | 6 | "Original IP detection extensions and xff_num_trusted_hops may not be mixed"); |
449 | 6 | } |
450 | 398 | } |
451 | | |
452 | 6.51k | original_ip_detection_extensions_.reserve(ip_detection_extensions.size()); |
453 | 6.51k | for (const auto& extension_config : ip_detection_extensions) { |
454 | 6.13k | auto* factory = |
455 | 6.13k | Envoy::Config::Utility::getFactory<Http::OriginalIPDetectionFactory>(extension_config); |
456 | 6.13k | if (!factory) { |
457 | 18 | throwEnvoyExceptionOrPanic( |
458 | 18 | fmt::format("Original IP detection extension not found: '{}'", extension_config.name())); |
459 | 18 | } |
460 | | |
461 | 6.11k | auto extension = factory->createExtension(extension_config.typed_config(), context_); |
462 | 6.11k | if (!extension) { |
463 | 0 | throwEnvoyExceptionOrPanic(fmt::format( |
464 | 0 | "Original IP detection extension could not be created: '{}'", extension_config.name())); |
465 | 0 | } |
466 | 6.11k | original_ip_detection_extensions_.push_back(extension); |
467 | 6.11k | } |
468 | | |
469 | 6.49k | const auto& header_mutation_extensions = config.early_header_mutation_extensions(); |
470 | 6.49k | early_header_mutation_extensions_.reserve(header_mutation_extensions.size()); |
471 | 6.49k | for (const auto& extension_config : header_mutation_extensions) { |
472 | 13 | auto* factory = |
473 | 13 | Envoy::Config::Utility::getFactory<Http::EarlyHeaderMutationFactory>(extension_config); |
474 | 13 | if (!factory) { |
475 | 13 | throwEnvoyExceptionOrPanic( |
476 | 13 | fmt::format("Early header mutation extension not found: '{}'", extension_config.name())); |
477 | 13 | } |
478 | | |
479 | 0 | auto extension = factory->createExtension(extension_config.typed_config(), context_); |
480 | 0 | if (!extension) { |
481 | 0 | throwEnvoyExceptionOrPanic(fmt::format( |
482 | 0 | "Early header mutation extension could not be created: '{}'", extension_config.name())); |
483 | 0 | } |
484 | 0 | early_header_mutation_extensions_.push_back(std::move(extension)); |
485 | 0 | } |
486 | | |
487 | | // If scoped RDS is enabled, avoid creating a route config provider. Route config providers |
488 | | // will be managed by the scoped routing logic instead. |
489 | 6.47k | switch (config.route_specifier_case()) { |
490 | 231 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
491 | 231 | RouteSpecifierCase::kRds: |
492 | 6.00k | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
493 | 6.00k | RouteSpecifierCase::kRouteConfig: |
494 | 6.00k | route_config_provider_ = Router::RouteConfigProviderUtil::create( |
495 | 6.00k | config, context_.getServerFactoryContext(), context_.messageValidationVisitor(), |
496 | 6.00k | context_.initManager(), stats_prefix_, route_config_provider_manager_); |
497 | 6.00k | break; |
498 | 101 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
499 | 101 | RouteSpecifierCase::kScopedRoutes: |
500 | 101 | scoped_routes_config_provider_ = Router::ScopedRoutesConfigProviderUtil::create( |
501 | 101 | config, context_.getServerFactoryContext(), context_.initManager(), stats_prefix_, |
502 | 101 | scoped_routes_config_provider_manager_); |
503 | 101 | scope_key_builder_ = Router::ScopedRoutesConfigProviderUtil::createScopeKeyBuilder(config); |
504 | 101 | break; |
505 | 0 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
506 | 0 | RouteSpecifierCase::ROUTE_SPECIFIER_NOT_SET: |
507 | 0 | PANIC_DUE_TO_CORRUPT_ENUM; |
508 | 6.47k | } |
509 | | |
510 | 5.42k | switch (config.forward_client_cert_details()) { |
511 | 0 | PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; |
512 | 4.63k | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
513 | 4.63k | SANITIZE: |
514 | 4.63k | forward_client_cert_ = Http::ForwardClientCertType::Sanitize; |
515 | 4.63k | break; |
516 | 544 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
517 | 544 | FORWARD_ONLY: |
518 | 544 | forward_client_cert_ = Http::ForwardClientCertType::ForwardOnly; |
519 | 544 | break; |
520 | 92 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
521 | 92 | APPEND_FORWARD: |
522 | 92 | forward_client_cert_ = Http::ForwardClientCertType::AppendForward; |
523 | 92 | break; |
524 | 77 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
525 | 77 | SANITIZE_SET: |
526 | 77 | forward_client_cert_ = Http::ForwardClientCertType::SanitizeSet; |
527 | 77 | break; |
528 | 80 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
529 | 80 | ALWAYS_FORWARD_ONLY: |
530 | 80 | forward_client_cert_ = Http::ForwardClientCertType::AlwaysForwardOnly; |
531 | 80 | break; |
532 | 5.42k | } |
533 | | |
534 | 5.42k | const auto& set_current_client_cert_details = config.set_current_client_cert_details(); |
535 | 5.42k | if (set_current_client_cert_details.cert()) { |
536 | 234 | set_current_client_cert_details_.push_back(Http::ClientCertDetailsType::Cert); |
537 | 234 | } |
538 | 5.42k | if (set_current_client_cert_details.chain()) { |
539 | 193 | set_current_client_cert_details_.push_back(Http::ClientCertDetailsType::Chain); |
540 | 193 | } |
541 | 5.42k | if (PROTOBUF_GET_WRAPPED_OR_DEFAULT(set_current_client_cert_details, subject, false)) { |
542 | 215 | set_current_client_cert_details_.push_back(Http::ClientCertDetailsType::Subject); |
543 | 215 | } |
544 | 5.42k | if (set_current_client_cert_details.uri()) { |
545 | 158 | set_current_client_cert_details_.push_back(Http::ClientCertDetailsType::URI); |
546 | 158 | } |
547 | 5.42k | if (set_current_client_cert_details.dns()) { |
548 | 120 | set_current_client_cert_details_.push_back(Http::ClientCertDetailsType::DNS); |
549 | 120 | } |
550 | | |
551 | 5.42k | if (config.has_add_user_agent() && config.add_user_agent().value()) { |
552 | 251 | user_agent_ = context_.localInfo().clusterName(); |
553 | 251 | } |
554 | | |
555 | 5.42k | if (config.has_tracing()) { |
556 | 876 | tracer_ = tracer_manager.getOrCreateTracer(getPerFilterTracerConfig(config)); |
557 | 876 | tracing_config_ = std::make_unique<Http::TracingConnectionManagerConfig>(context.direction(), |
558 | 876 | config.tracing()); |
559 | 876 | } |
560 | | |
561 | 5.42k | for (const auto& access_log : config.access_log()) { |
562 | 2.97k | AccessLog::InstanceSharedPtr current_access_log = |
563 | 2.97k | AccessLog::AccessLogFactory::fromProto(access_log, context_); |
564 | 2.97k | access_logs_.push_back(current_access_log); |
565 | 2.97k | } |
566 | | |
567 | 5.42k | if (config.has_access_log_options()) { |
568 | 309 | if (config.flush_access_log_on_new_request() /* deprecated */) { |
569 | 27 | throwEnvoyExceptionOrPanic( |
570 | 27 | "Only one of flush_access_log_on_new_request or access_log_options can be specified."); |
571 | 27 | } |
572 | | |
573 | 282 | if (config.has_access_log_flush_interval()) { |
574 | 3 | throwEnvoyExceptionOrPanic( |
575 | 3 | "Only one of access_log_flush_interval or access_log_options can be specified."); |
576 | 3 | } |
577 | | |
578 | 279 | flush_access_log_on_new_request_ = |
579 | 279 | config.access_log_options().flush_access_log_on_new_request(); |
580 | 279 | flush_log_on_tunnel_successfully_established_ = |
581 | 279 | config.access_log_options().flush_log_on_tunnel_successfully_established(); |
582 | | |
583 | 279 | if (config.access_log_options().has_access_log_flush_interval()) { |
584 | 24 | access_log_flush_interval_ = std::chrono::milliseconds(DurationUtil::durationToMilliseconds( |
585 | 24 | config.access_log_options().access_log_flush_interval())); |
586 | 24 | } |
587 | 5.11k | } else { |
588 | 5.11k | flush_access_log_on_new_request_ = config.flush_access_log_on_new_request(); |
589 | | |
590 | 5.11k | if (config.has_access_log_flush_interval()) { |
591 | 198 | access_log_flush_interval_ = std::chrono::milliseconds( |
592 | 198 | DurationUtil::durationToMilliseconds(config.access_log_flush_interval())); |
593 | 198 | } |
594 | 5.11k | } |
595 | | |
596 | 5.39k | server_transformation_ = config.server_header_transformation(); |
597 | | |
598 | 5.39k | if (!config.scheme_header_transformation().scheme_to_overwrite().empty()) { |
599 | 1 | scheme_to_set_ = config.scheme_header_transformation().scheme_to_overwrite(); |
600 | 1 | } |
601 | | |
602 | 5.39k | if (!config.server_name().empty()) { |
603 | 393 | server_name_ = config.server_name(); |
604 | 5.00k | } else { |
605 | 5.00k | server_name_ = Http::DefaultServerString::get(); |
606 | 5.00k | } |
607 | | |
608 | 5.39k | switch (config.codec_type()) { |
609 | 0 | PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; |
610 | 1.88k | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
611 | 1.88k | AUTO: |
612 | 1.88k | codec_type_ = CodecType::AUTO; |
613 | 1.88k | break; |
614 | 1.26k | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
615 | 1.26k | HTTP1: |
616 | 1.26k | codec_type_ = CodecType::HTTP1; |
617 | 1.26k | break; |
618 | 1.72k | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
619 | 1.72k | HTTP2: |
620 | 1.72k | codec_type_ = CodecType::HTTP2; |
621 | 1.72k | break; |
622 | 144 | case envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager:: |
623 | 144 | HTTP3: |
624 | 144 | #ifdef ENVOY_ENABLE_QUIC |
625 | 144 | codec_type_ = CodecType::HTTP3; |
626 | 144 | if (!context_.isQuicListener()) { |
627 | 144 | throwEnvoyExceptionOrPanic("HTTP/3 codec configured on non-QUIC listener."); |
628 | 144 | } |
629 | | #else |
630 | | throwEnvoyExceptionOrPanic("HTTP3 configured but not enabled in the build."); |
631 | | #endif |
632 | 0 | break; |
633 | 5.39k | } |
634 | 4.87k | if (codec_type_ != CodecType::HTTP3 && context_.isQuicListener()) { |
635 | 0 | throwEnvoyExceptionOrPanic("Non-HTTP/3 codec configured on QUIC listener."); |
636 | 0 | } |
637 | | |
638 | 4.87k | Http::FilterChainHelper<Server::Configuration::FactoryContext, |
639 | 4.87k | Server::Configuration::NamedHttpFilterConfigFactory> |
640 | 4.87k | helper(filter_config_provider_manager_, context_.getServerFactoryContext(), |
641 | 4.87k | context_.clusterManager(), context_, stats_prefix_); |
642 | 4.87k | THROW_IF_NOT_OK(helper.processFilters(config.http_filters(), "http", "http", filter_factories_)); |
643 | | |
644 | 4.83k | for (const auto& upgrade_config : config.upgrade_configs()) { |
645 | 1.26k | const std::string& name = upgrade_config.upgrade_type(); |
646 | 1.26k | const bool enabled = upgrade_config.has_enabled() ? upgrade_config.enabled().value() : true; |
647 | 1.26k | if (findUpgradeCaseInsensitive(upgrade_filter_factories_, name) != |
648 | 1.26k | upgrade_filter_factories_.end()) { |
649 | 92 | throwEnvoyExceptionOrPanic( |
650 | 92 | fmt::format("Error: multiple upgrade configs with the same name: '{}'", name)); |
651 | 92 | } |
652 | 1.16k | if (!upgrade_config.filters().empty()) { |
653 | 79 | std::unique_ptr<FilterFactoriesList> factories = std::make_unique<FilterFactoriesList>(); |
654 | 79 | Http::DependencyManager upgrade_dependency_manager; |
655 | 79 | THROW_IF_NOT_OK( |
656 | 79 | helper.processFilters(upgrade_config.filters(), name, "http upgrade", *factories)); |
657 | | // TODO(auni53): Validate encode dependencies too. |
658 | 74 | auto status = upgrade_dependency_manager.validDecodeDependencies(); |
659 | 74 | if (!status.ok()) { |
660 | 0 | throwEnvoyExceptionOrPanic(std::string(status.message())); |
661 | 0 | } |
662 | | |
663 | 74 | upgrade_filter_factories_.emplace( |
664 | 74 | std::make_pair(name, FilterConfig{std::move(factories), enabled})); |
665 | 1.09k | } else { |
666 | 1.09k | std::unique_ptr<FilterFactoriesList> factories(nullptr); |
667 | 1.09k | upgrade_filter_factories_.emplace( |
668 | 1.09k | std::make_pair(name, FilterConfig{std::move(factories), enabled})); |
669 | 1.09k | } |
670 | 1.16k | } |
671 | 4.83k | } |
672 | | |
673 | | Http::ServerConnectionPtr HttpConnectionManagerConfig::createCodec( |
674 | | Network::Connection& connection, const Buffer::Instance& data, |
675 | 3.09k | Http::ServerConnectionCallbacks& callbacks, Server::OverloadManager& overload_manager) { |
676 | 3.09k | switch (codec_type_) { |
677 | 495 | case CodecType::HTTP1: |
678 | 495 | return std::make_unique<Http::Http1::ServerConnectionImpl>( |
679 | 495 | connection, Http::Http1::CodecStats::atomicGet(http1_codec_stats_, context_.scope()), |
680 | 495 | callbacks, http1_settings_, maxRequestHeadersKb(), maxRequestHeadersCount(), |
681 | 495 | headersWithUnderscoresAction(), overload_manager); |
682 | 1.41k | case CodecType::HTTP2: |
683 | 1.41k | return std::make_unique<Http::Http2::ServerConnectionImpl>( |
684 | 1.41k | connection, callbacks, |
685 | 1.41k | Http::Http2::CodecStats::atomicGet(http2_codec_stats_, context_.scope()), |
686 | 1.41k | context_.api().randomGenerator(), http2_options_, maxRequestHeadersKb(), |
687 | 1.41k | maxRequestHeadersCount(), headersWithUnderscoresAction(), overload_manager); |
688 | 0 | case CodecType::HTTP3: |
689 | 0 | return Config::Utility::getAndCheckFactoryByName<QuicHttpServerConnectionFactory>( |
690 | 0 | "quic.http_server_connection.default") |
691 | 0 | .createQuicHttpServerConnectionImpl( |
692 | 0 | connection, callbacks, |
693 | 0 | Http::Http3::CodecStats::atomicGet(http3_codec_stats_, context_.scope()), |
694 | 0 | http3_options_, maxRequestHeadersKb(), maxRequestHeadersCount(), |
695 | 0 | headersWithUnderscoresAction()); |
696 | 1.18k | case CodecType::AUTO: |
697 | 1.18k | return Http::ConnectionManagerUtility::autoCreateCodec( |
698 | 1.18k | connection, data, callbacks, context_.scope(), context_.api().randomGenerator(), |
699 | 1.18k | http1_codec_stats_, http2_codec_stats_, http1_settings_, http2_options_, |
700 | 1.18k | maxRequestHeadersKb(), maxRequestHeadersCount(), headersWithUnderscoresAction(), |
701 | 1.18k | overload_manager); |
702 | 3.09k | } |
703 | 0 | PANIC_DUE_TO_CORRUPT_ENUM; |
704 | 0 | } |
705 | | |
706 | | bool HttpConnectionManagerConfig::createFilterChain(Http::FilterChainManager& manager, bool, |
707 | 2.48k | const Http::FilterChainOptions& options) const { |
708 | 2.48k | Http::FilterChainUtility::createFilterChainForFactories(manager, options, filter_factories_); |
709 | 2.48k | return true; |
710 | 2.48k | } |
711 | | |
712 | | bool HttpConnectionManagerConfig::createUpgradeFilterChain( |
713 | | absl::string_view upgrade_type, |
714 | | const Http::FilterChainFactory::UpgradeMap* per_route_upgrade_map, |
715 | 0 | Http::FilterChainManager& callbacks) const { |
716 | 0 | bool route_enabled = false; |
717 | 0 | if (per_route_upgrade_map) { |
718 | 0 | auto route_it = findUpgradeBoolCaseInsensitive(*per_route_upgrade_map, upgrade_type); |
719 | 0 | if (route_it != per_route_upgrade_map->end()) { |
720 | | // Upgrades explicitly not allowed on this route. |
721 | 0 | if (route_it->second == false) { |
722 | 0 | return false; |
723 | 0 | } |
724 | | // Upgrades explicitly enabled on this route. |
725 | 0 | route_enabled = true; |
726 | 0 | } |
727 | 0 | } |
728 | | |
729 | 0 | auto it = findUpgradeCaseInsensitive(upgrade_filter_factories_, upgrade_type); |
730 | 0 | if ((it == upgrade_filter_factories_.end() || !it->second.allow_upgrade) && !route_enabled) { |
731 | | // Either the HCM disables upgrades and the route-config does not override, |
732 | | // or neither is configured for this upgrade. |
733 | 0 | return false; |
734 | 0 | } |
735 | 0 | const FilterFactoriesList* filters_to_use = &filter_factories_; |
736 | 0 | if (it != upgrade_filter_factories_.end() && it->second.filter_factories != nullptr) { |
737 | 0 | filters_to_use = it->second.filter_factories.get(); |
738 | 0 | } |
739 | |
|
740 | 0 | Http::FilterChainUtility::createFilterChainForFactories( |
741 | 0 | callbacks, Http::EmptyFilterChainOptions{}, *filters_to_use); |
742 | 0 | return true; |
743 | 0 | } |
744 | | |
745 | 0 | const Network::Address::Instance& HttpConnectionManagerConfig::localAddress() { |
746 | 0 | return *context_.localInfo().address(); |
747 | 0 | } |
748 | | |
749 | | /** |
750 | | * Determines what tracing provider to use for a given |
751 | | * "envoy.filters.network.http_connection_manager" filter instance. |
752 | | */ |
753 | | const envoy::config::trace::v3::Tracing_Http* HttpConnectionManagerConfig::getPerFilterTracerConfig( |
754 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
755 | 876 | config) { |
756 | | // Give precedence to tracing provider configuration defined as part of |
757 | | // "envoy.filters.network.http_connection_manager" filter config. |
758 | 876 | if (config.tracing().has_provider()) { |
759 | 31 | return &config.tracing().provider(); |
760 | 31 | } |
761 | | // Otherwise, for the sake of backwards compatibility, fall back to using tracing provider |
762 | | // configuration defined in the bootstrap config. |
763 | 845 | if (context_.httpContext().defaultTracingConfig().has_http()) { |
764 | 0 | return &context_.httpContext().defaultTracingConfig().http(); |
765 | 0 | } |
766 | 845 | return nullptr; |
767 | 845 | } |
768 | | |
769 | | #ifdef ENVOY_ENABLE_UHV |
770 | | ::Envoy::Http::HeaderValidatorStats& |
771 | | HttpConnectionManagerConfig::getHeaderValidatorStats([[maybe_unused]] Http::Protocol protocol) { |
772 | | switch (protocol) { |
773 | | case Http::Protocol::Http10: |
774 | | case Http::Protocol::Http11: |
775 | | return Http::Http1::CodecStats::atomicGet(http1_codec_stats_, context_.scope()); |
776 | | case Http::Protocol::Http2: |
777 | | return Http::Http2::CodecStats::atomicGet(http2_codec_stats_, context_.scope()); |
778 | | case Http::Protocol::Http3: |
779 | | return Http::Http3::CodecStats::atomicGet(http3_codec_stats_, context_.scope()); |
780 | | } |
781 | | PANIC_DUE_TO_CORRUPT_ENUM; |
782 | | } |
783 | | #endif |
784 | | |
785 | | std::function<Http::ApiListenerPtr(Network::ReadFilterCallbacks&)> |
786 | | HttpConnectionManagerFactory::createHttpConnectionManagerFactoryFromProto( |
787 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
788 | | proto_config, |
789 | 0 | Server::Configuration::FactoryContext& context, bool clear_hop_by_hop_headers) { |
790 | 0 | Utility::Singletons singletons = Utility::createSingletons(context); |
791 | |
|
792 | 0 | auto filter_config = Utility::createConfig( |
793 | 0 | proto_config, context, *singletons.date_provider_, *singletons.route_config_provider_manager_, |
794 | 0 | *singletons.scoped_routes_config_provider_manager_, *singletons.tracer_manager_, |
795 | 0 | *singletons.filter_config_provider_manager_); |
796 | | |
797 | | // This lambda captures the shared_ptrs created above, thus preserving the |
798 | | // reference count. |
799 | | // Keep in mind the lambda capture list **doesn't** determine the destruction order, but it's fine |
800 | | // as these captured objects are also global singletons. |
801 | 0 | return [singletons, filter_config, &context, clear_hop_by_hop_headers]( |
802 | 0 | Network::ReadFilterCallbacks& read_callbacks) -> Http::ApiListenerPtr { |
803 | 0 | auto conn_manager = std::make_unique<Http::ConnectionManagerImpl>( |
804 | 0 | *filter_config, context.drainDecision(), context.api().randomGenerator(), |
805 | 0 | context.httpContext(), context.runtime(), context.localInfo(), context.clusterManager(), |
806 | 0 | context.overloadManager(), context.mainThreadDispatcher().timeSource()); |
807 | 0 | if (!clear_hop_by_hop_headers) { |
808 | 0 | conn_manager->setClearHopByHopResponseHeaders(false); |
809 | 0 | } |
810 | | |
811 | | // This factory creates a new ConnectionManagerImpl in the absence of its usual environment as |
812 | | // an L4 filter, so this factory needs to take a few actions. |
813 | | |
814 | | // When a new connection is creating its filter chain it hydrates the factory with a filter |
815 | | // manager which provides the ConnectionManager with its "read_callbacks". |
816 | 0 | conn_manager->initializeReadFilterCallbacks(read_callbacks); |
817 | | |
818 | | // When the connection first calls onData on the ConnectionManager, the ConnectionManager |
819 | | // creates a codec. Here we force create a codec as onData will not be called. |
820 | 0 | Buffer::OwnedImpl dummy; |
821 | 0 | conn_manager->createCodec(dummy); |
822 | |
|
823 | 0 | return conn_manager; |
824 | 0 | }; |
825 | 0 | } |
826 | | |
827 | | } // namespace HttpConnectionManager |
828 | | } // namespace NetworkFilters |
829 | | } // namespace Extensions |
830 | | } // namespace Envoy |