LCOV - code coverage report
Current view: top level - source/extensions/upstreams/http - config.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 55 105 52.4 %
Date: 2024-01-05 06:35:25 Functions: 10 10 100.0 %

          Line data    Source code
       1             : #include "source/extensions/upstreams/http/config.h"
       2             : 
       3             : #include <chrono>
       4             : #include <memory>
       5             : #include <string>
       6             : #include <vector>
       7             : 
       8             : #include "envoy/config/cluster/v3/cluster.pb.h"
       9             : #include "envoy/config/core/v3/base.pb.h"
      10             : #include "envoy/extensions/http/header_validators/envoy_default/v3/header_validator.pb.h"
      11             : #include "envoy/http/header_validator_factory.h"
      12             : #include "envoy/upstream/upstream.h"
      13             : 
      14             : #include "source/common/config/utility.h"
      15             : #include "source/common/http/http1/settings.h"
      16             : #include "source/common/http/utility.h"
      17             : #include "source/common/protobuf/utility.h"
      18             : 
      19             : namespace Envoy {
      20             : namespace Extensions {
      21             : namespace Upstreams {
      22             : namespace Http {
      23             : namespace {
      24             : 
      25             : const envoy::config::core::v3::Http1ProtocolOptions&
      26         119 : getHttpOptions(const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options) {
      27         119 :   if (options.has_use_downstream_protocol_config()) {
      28           0 :     return options.use_downstream_protocol_config().http_protocol_options();
      29           0 :   }
      30         119 :   if (options.has_auto_config()) {
      31           0 :     return options.auto_config().http_protocol_options();
      32           0 :   }
      33         119 :   return options.explicit_http_config().http_protocol_options();
      34         119 : }
      35             : 
      36             : const envoy::config::core::v3::Http2ProtocolOptions&
      37         119 : getHttp2Options(const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options) {
      38         119 :   if (options.has_use_downstream_protocol_config()) {
      39           0 :     return options.use_downstream_protocol_config().http2_protocol_options();
      40           0 :   }
      41         119 :   if (options.has_auto_config()) {
      42           0 :     return options.auto_config().http2_protocol_options();
      43           0 :   }
      44         119 :   return options.explicit_http_config().http2_protocol_options();
      45         119 : }
      46             : 
      47             : const envoy::config::core::v3::Http3ProtocolOptions&
      48         119 : getHttp3Options(const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options) {
      49         119 :   if (options.has_use_downstream_protocol_config() &&
      50         119 :       options.use_downstream_protocol_config().has_http3_protocol_options()) {
      51           0 :     return options.use_downstream_protocol_config().http3_protocol_options();
      52           0 :   }
      53         119 :   if (options.has_auto_config()) {
      54           0 :     return options.auto_config().http3_protocol_options();
      55           0 :   }
      56         119 :   return options.explicit_http_config().http3_protocol_options();
      57         119 : }
      58             : 
      59         119 : bool useHttp2(const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options) {
      60         119 :   if (options.has_explicit_http_config() &&
      61         119 :       options.explicit_http_config().has_http2_protocol_options()) {
      62         119 :     return true;
      63         119 :   } else if (options.has_use_downstream_protocol_config() &&
      64           0 :              options.use_downstream_protocol_config().has_http2_protocol_options()) {
      65           0 :     return true;
      66           0 :   } else if (options.has_auto_config()) {
      67           0 :     return true;
      68           0 :   }
      69           0 :   return false;
      70         119 : }
      71             : 
      72         119 : bool useHttp3(const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options) {
      73         119 :   if (options.has_explicit_http_config() &&
      74         119 :       options.explicit_http_config().has_http3_protocol_options()) {
      75           0 :     return true;
      76         119 :   } else if (options.has_use_downstream_protocol_config() &&
      77         119 :              options.use_downstream_protocol_config().has_http3_protocol_options()) {
      78           0 :     return true;
      79         119 :   } else if (options.has_auto_config() && options.auto_config().has_http3_protocol_options()) {
      80           0 :     return true;
      81           0 :   }
      82         119 :   return false;
      83         119 : }
      84             : 
      85             : absl::optional<const envoy::config::core::v3::AlternateProtocolsCacheOptions>
      86             : getAlternateProtocolsCacheOptions(
      87             :     const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options,
      88         119 :     Server::Configuration::ServerFactoryContext& server_context) {
      89         119 :   if (options.has_auto_config() && options.auto_config().has_http3_protocol_options()) {
      90           0 :     if (!options.auto_config().has_alternate_protocols_cache_options()) {
      91           0 :       throwEnvoyExceptionOrPanic(
      92           0 :           fmt::format("alternate protocols cache must be configured when HTTP/3 "
      93           0 :                       "is enabled with auto_config"));
      94           0 :     }
      95           0 :     auto cache_options = options.auto_config().alternate_protocols_cache_options();
      96           0 :     if (cache_options.has_key_value_store_config() && server_context.options().concurrency() != 1) {
      97           0 :       throwEnvoyExceptionOrPanic(
      98           0 :           fmt::format("options has key value store but Envoy has concurrency = {} : {}",
      99           0 :                       server_context.options().concurrency(), cache_options.DebugString()));
     100           0 :     }
     101             : 
     102           0 :     return cache_options;
     103           0 :   }
     104         119 :   return absl::nullopt;
     105         119 : }
     106             : 
     107             : Envoy::Http::HeaderValidatorFactoryPtr createHeaderValidatorFactory(
     108             :     [[maybe_unused]] const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options,
     109         119 :     [[maybe_unused]] Server::Configuration::ServerFactoryContext& server_context) {
     110             : 
     111         119 :   Envoy::Http::HeaderValidatorFactoryPtr header_validator_factory;
     112             : #ifdef ENVOY_ENABLE_UHV
     113             :   if (!Runtime::runtimeFeatureEnabled(
     114             :           "envoy.reloadable_features.enable_universal_header_validator")) {
     115             :     // This will cause codecs to use legacy header validation and path normalization
     116             :     return nullptr;
     117             :   }
     118             :   ::envoy::config::core::v3::TypedExtensionConfig legacy_header_validator_config;
     119             :   if (!options.has_header_validation_config()) {
     120             :     // If header validator is not configured ensure that the defaults match Envoy's original
     121             :     // behavior.
     122             :     ::envoy::extensions::http::header_validators::envoy_default::v3::HeaderValidatorConfig
     123             :         uhv_config;
     124             :     uhv_config.mutable_http1_protocol_options()->set_allow_chunked_length(
     125             :         getHttpOptions(options).allow_chunked_length());
     126             :     legacy_header_validator_config.set_name("default_envoy_uhv_from_legacy_settings");
     127             :     legacy_header_validator_config.mutable_typed_config()->PackFrom(uhv_config);
     128             :   }
     129             : 
     130             :   const ::envoy::config::core::v3::TypedExtensionConfig& header_validator_config =
     131             :       options.has_header_validation_config() ? options.header_validation_config()
     132             :                                              : legacy_header_validator_config;
     133             : 
     134             :   auto* factory = Envoy::Config::Utility::getFactory<Envoy::Http::HeaderValidatorFactoryConfig>(
     135             :       header_validator_config);
     136             :   if (!factory) {
     137             :     throwEnvoyExceptionOrPanic(
     138             :         fmt::format("Header validator extension not found: '{}'", header_validator_config.name()));
     139             :   }
     140             : 
     141             :   header_validator_factory =
     142             :       factory->createFromProto(header_validator_config.typed_config(), server_context);
     143             :   if (!header_validator_factory) {
     144             :     throwEnvoyExceptionOrPanic(fmt::format("Header validator extension could not be created: '{}'",
     145             :                                            header_validator_config.name()));
     146             :   }
     147             : #else
     148         119 :   if (options.has_header_validation_config()) {
     149           0 :     throwEnvoyExceptionOrPanic(
     150           0 :         fmt::format("This Envoy binary does not support header validator extensions: '{}'",
     151           0 :                     options.header_validation_config().name()));
     152           0 :   }
     153             : 
     154         119 :   if (Runtime::runtimeFeatureEnabled(
     155         119 :           "envoy.reloadable_features.enable_universal_header_validator")) {
     156           0 :     throwEnvoyExceptionOrPanic(
     157           0 :         "Header validator can not be enabled since this Envoy binary does not support it.");
     158           0 :   }
     159         119 : #endif
     160         119 :   return header_validator_factory;
     161         119 : }
     162             : 
     163             : } // namespace
     164             : 
     165             : uint64_t ProtocolOptionsConfigImpl::parseFeatures(const envoy::config::cluster::v3::Cluster& config,
     166         159 :                                                   const ProtocolOptionsConfigImpl& options) {
     167         159 :   uint64_t features = 0;
     168             : 
     169         159 :   if (options.use_http2_) {
     170         119 :     features |= Upstream::ClusterInfo::Features::HTTP2;
     171         119 :   }
     172         159 :   if (options.use_http3_) {
     173           0 :     features |= Upstream::ClusterInfo::Features::HTTP3;
     174           0 :   }
     175         159 :   if (options.use_downstream_protocol_) {
     176           0 :     features |= Upstream::ClusterInfo::Features::USE_DOWNSTREAM_PROTOCOL;
     177           0 :   }
     178         159 :   if (options.use_alpn_) {
     179           0 :     features |= Upstream::ClusterInfo::Features::USE_ALPN;
     180           0 :   }
     181         159 :   if (config.close_connections_on_host_health_failure()) {
     182           0 :     features |= Upstream::ClusterInfo::Features::CLOSE_CONNECTIONS_ON_HOST_HEALTH_FAILURE;
     183           0 :   }
     184         159 :   return features;
     185         159 : }
     186             : 
     187             : ProtocolOptionsConfigImpl::ProtocolOptionsConfigImpl(
     188             :     const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options,
     189             :     Server::Configuration::ServerFactoryContext& server_context)
     190             :     : http1_settings_(Envoy::Http::Http1::parseHttp1Settings(
     191             :           getHttpOptions(options), server_context.messageValidationVisitor())),
     192             :       http2_options_(Http2::Utility::initializeAndValidateOptions(getHttp2Options(options))),
     193             :       http3_options_(getHttp3Options(options)),
     194             :       common_http_protocol_options_(options.common_http_protocol_options()),
     195             :       upstream_http_protocol_options_(
     196             :           options.has_upstream_http_protocol_options()
     197             :               ? absl::make_optional<envoy::config::core::v3::UpstreamHttpProtocolOptions>(
     198             :                     options.upstream_http_protocol_options())
     199             :               : absl::nullopt),
     200             :       http_filters_(options.http_filters()),
     201             :       alternate_protocol_cache_options_(getAlternateProtocolsCacheOptions(options, server_context)),
     202             :       header_validator_factory_(createHeaderValidatorFactory(options, server_context)),
     203             :       use_downstream_protocol_(options.has_use_downstream_protocol_config()),
     204             :       use_http2_(useHttp2(options)), use_http3_(useHttp3(options)),
     205         119 :       use_alpn_(options.has_auto_config()) {}
     206             : 
     207             : ProtocolOptionsConfigImpl::ProtocolOptionsConfigImpl(
     208             :     const envoy::config::core::v3::Http1ProtocolOptions& http1_settings,
     209             :     const envoy::config::core::v3::Http2ProtocolOptions& http2_options,
     210             :     const envoy::config::core::v3::HttpProtocolOptions& common_options,
     211             :     const absl::optional<envoy::config::core::v3::UpstreamHttpProtocolOptions> upstream_options,
     212             :     bool use_downstream_protocol, bool use_http2,
     213             :     ProtobufMessage::ValidationVisitor& validation_visitor)
     214             :     : http1_settings_(Envoy::Http::Http1::parseHttp1Settings(http1_settings, validation_visitor)),
     215             :       http2_options_(Http2::Utility::initializeAndValidateOptions(http2_options)),
     216             :       common_http_protocol_options_(common_options),
     217             :       upstream_http_protocol_options_(upstream_options),
     218          40 :       use_downstream_protocol_(use_downstream_protocol), use_http2_(use_http2) {}
     219             : 
     220             : LEGACY_REGISTER_FACTORY(ProtocolOptionsConfigFactory, Server::Configuration::ProtocolOptionsFactory,
     221             :                         "envoy.upstreams.http.http_protocol_options");
     222             : } // namespace Http
     223             : } // namespace Upstreams
     224             : } // namespace Extensions
     225             : } // namespace Envoy

Generated by: LCOV version 1.15