LCOV - code coverage report
Current view: top level - source/common/router - scoped_config_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 0 121 0.0 %
Date: 2024-01-05 06:35:25 Functions: 0 10 0.0 %

          Line data    Source code
       1             : #include "source/common/router/scoped_config_impl.h"
       2             : 
       3             : #include "envoy/config/route/v3/scoped_route.pb.h"
       4             : #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h"
       5             : 
       6             : #include "source/common/protobuf/utility.h"
       7             : 
       8             : namespace Envoy {
       9             : namespace Router {
      10             : 
      11           0 : bool ScopeKey::operator!=(const ScopeKey& other) const { return !(*this == other); }
      12             : 
      13           0 : bool ScopeKey::operator==(const ScopeKey& other) const {
      14           0 :   if (fragments_.empty() || other.fragments_.empty()) {
      15             :     // An empty key equals to nothing, "NULL" != "NULL".
      16           0 :     return false;
      17           0 :   }
      18           0 :   return this->hash() == other.hash();
      19           0 : }
      20             : 
      21             : HeaderValueExtractorImpl::HeaderValueExtractorImpl(
      22             :     ScopedRoutes::ScopeKeyBuilder::FragmentBuilder&& config)
      23             :     : FragmentBuilderBase(std::move(config)),
      24           0 :       header_value_extractor_config_(config_.header_value_extractor()) {
      25           0 :   ASSERT(config_.type_case() ==
      26           0 :              ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::kHeaderValueExtractor,
      27           0 :          "header_value_extractor is not set.");
      28           0 :   if (header_value_extractor_config_.extract_type_case() ==
      29           0 :       ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::HeaderValueExtractor::kIndex) {
      30           0 :     if (header_value_extractor_config_.index() != 0 &&
      31           0 :         header_value_extractor_config_.element_separator().empty()) {
      32           0 :       ProtoExceptionUtil::throwProtoValidationException(
      33           0 :           "Index > 0 for empty string element separator.", config_);
      34           0 :     }
      35           0 :   }
      36           0 :   if (header_value_extractor_config_.extract_type_case() ==
      37           0 :       ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::HeaderValueExtractor::EXTRACT_TYPE_NOT_SET) {
      38           0 :     ProtoExceptionUtil::throwProtoValidationException("HeaderValueExtractor extract_type not set.",
      39           0 :                                                       config_);
      40           0 :   }
      41           0 : }
      42             : 
      43             : std::unique_ptr<ScopeKeyFragmentBase>
      44           0 : HeaderValueExtractorImpl::computeFragment(const Http::HeaderMap& headers) const {
      45           0 :   const auto header_entry =
      46           0 :       headers.get(Envoy::Http::LowerCaseString(header_value_extractor_config_.name()));
      47           0 :   if (header_entry.empty()) {
      48           0 :     return nullptr;
      49           0 :   }
      50             : 
      51             :   // This is an implicitly untrusted header, so per the API documentation only the first
      52             :   // value is used.
      53           0 :   std::vector<absl::string_view> elements{header_entry[0]->value().getStringView()};
      54           0 :   if (header_value_extractor_config_.element_separator().length() > 0) {
      55           0 :     elements = absl::StrSplit(header_entry[0]->value().getStringView(),
      56           0 :                               header_value_extractor_config_.element_separator());
      57           0 :   }
      58           0 :   switch (header_value_extractor_config_.extract_type_case()) {
      59           0 :   case ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::HeaderValueExtractor::kElement:
      60           0 :     for (const auto& element : elements) {
      61           0 :       std::pair<absl::string_view, absl::string_view> key_value = absl::StrSplit(
      62           0 :           element, absl::MaxSplits(header_value_extractor_config_.element().separator(), 1));
      63           0 :       if (key_value.first == header_value_extractor_config_.element().key()) {
      64           0 :         return std::make_unique<StringKeyFragment>(key_value.second);
      65           0 :       }
      66           0 :     }
      67           0 :     break;
      68           0 :   case ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::HeaderValueExtractor::kIndex:
      69           0 :     if (header_value_extractor_config_.index() < elements.size()) {
      70           0 :       return std::make_unique<StringKeyFragment>(elements[header_value_extractor_config_.index()]);
      71           0 :     }
      72           0 :     break;
      73           0 :   case ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::HeaderValueExtractor::EXTRACT_TYPE_NOT_SET:
      74           0 :     PANIC("not reached");
      75           0 :   }
      76             : 
      77           0 :   return nullptr;
      78           0 : }
      79             : 
      80             : ScopedRouteInfo::ScopedRouteInfo(envoy::config::route::v3::ScopedRouteConfiguration config_proto,
      81             :                                  ConfigConstSharedPtr route_config)
      82             :     : config_proto_(config_proto), route_config_(route_config),
      83           0 :       config_hash_(MessageUtil::hash(config_proto)) {
      84             :   // TODO(stevenzzzz): Maybe worth a KeyBuilder abstraction when there are more than one type of
      85             :   // Fragment.
      86           0 :   for (const auto& fragment : config_proto_.key().fragments()) {
      87           0 :     switch (fragment.type_case()) {
      88           0 :     case envoy::config::route::v3::ScopedRouteConfiguration::Key::Fragment::TypeCase::kStringKey:
      89           0 :       scope_key_.addFragment(std::make_unique<StringKeyFragment>(fragment.string_key()));
      90           0 :       break;
      91           0 :     case envoy::config::route::v3::ScopedRouteConfiguration::Key::Fragment::TypeCase::TYPE_NOT_SET:
      92           0 :       PANIC("not implemented");
      93           0 :     }
      94           0 :   }
      95           0 : }
      96             : 
      97             : ScopeKeyBuilderImpl::ScopeKeyBuilderImpl(ScopedRoutes::ScopeKeyBuilder&& config)
      98           0 :     : ScopeKeyBuilderBase(std::move(config)) {
      99           0 :   for (const auto& fragment_builder : config_.fragments()) {
     100           0 :     switch (fragment_builder.type_case()) {
     101           0 :     case ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::kHeaderValueExtractor:
     102           0 :       fragment_builders_.emplace_back(std::make_unique<HeaderValueExtractorImpl>(
     103           0 :           ScopedRoutes::ScopeKeyBuilder::FragmentBuilder(fragment_builder)));
     104           0 :       break;
     105           0 :     case ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::TYPE_NOT_SET:
     106           0 :       PANIC("not implemented");
     107           0 :     }
     108           0 :   }
     109           0 : }
     110             : 
     111           0 : ScopeKeyPtr ScopeKeyBuilderImpl::computeScopeKey(const Http::HeaderMap& headers) const {
     112           0 :   ScopeKey key;
     113           0 :   for (const auto& builder : fragment_builders_) {
     114             :     // returns nullopt if a null fragment is found.
     115           0 :     std::unique_ptr<ScopeKeyFragmentBase> fragment = builder->computeFragment(headers);
     116           0 :     if (fragment == nullptr) {
     117           0 :       return nullptr;
     118           0 :     }
     119           0 :     key.addFragment(std::move(fragment));
     120           0 :   }
     121           0 :   return std::make_unique<ScopeKey>(std::move(key));
     122           0 : }
     123             : 
     124             : void ScopedConfigImpl::addOrUpdateRoutingScopes(
     125           0 :     const std::vector<ScopedRouteInfoConstSharedPtr>& scoped_route_infos) {
     126           0 :   for (auto& scoped_route_info : scoped_route_infos) {
     127           0 :     const auto iter = scoped_route_info_by_name_.find(scoped_route_info->scopeName());
     128           0 :     if (iter != scoped_route_info_by_name_.end()) {
     129           0 :       ASSERT(scoped_route_info_by_key_.contains(iter->second->scopeKey().hash()));
     130           0 :       scoped_route_info_by_key_.erase(iter->second->scopeKey().hash());
     131           0 :     }
     132           0 :     scoped_route_info_by_name_[scoped_route_info->scopeName()] = scoped_route_info;
     133           0 :     scoped_route_info_by_key_[scoped_route_info->scopeKey().hash()] = scoped_route_info;
     134           0 :   }
     135           0 : }
     136             : 
     137           0 : void ScopedConfigImpl::removeRoutingScopes(const std::vector<std::string>& scope_names) {
     138           0 :   for (std::string const& scope_name : scope_names) {
     139           0 :     const auto iter = scoped_route_info_by_name_.find(scope_name);
     140           0 :     if (iter != scoped_route_info_by_name_.end()) {
     141           0 :       ASSERT(scoped_route_info_by_key_.contains(iter->second->scopeKey().hash()));
     142           0 :       scoped_route_info_by_key_.erase(iter->second->scopeKey().hash());
     143           0 :       scoped_route_info_by_name_.erase(iter);
     144           0 :     }
     145           0 :   }
     146           0 : }
     147             : 
     148           0 : Router::ConfigConstSharedPtr ScopedConfigImpl::getRouteConfig(const ScopeKeyPtr& scope_key) const {
     149           0 :   if (scope_key == nullptr) {
     150           0 :     return nullptr;
     151           0 :   }
     152           0 :   auto iter = scoped_route_info_by_key_.find(scope_key->hash());
     153           0 :   if (iter != scoped_route_info_by_key_.end()) {
     154           0 :     return iter->second->routeConfig();
     155           0 :   }
     156           0 :   return nullptr;
     157           0 : }
     158             : 
     159             : } // namespace Router
     160             : } // namespace Envoy

Generated by: LCOV version 1.15