Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions source/common/http/utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -888,18 +888,6 @@ void Utility::transformUpgradeResponseFromH2toH1(ResponseHeaderMap& headers,
}
}

const Router::RouteSpecificFilterConfig*
Utility::resolveMostSpecificPerFilterConfigGeneric(const std::string& filter_name,
const Router::RouteConstSharedPtr& route) {

const Router::RouteSpecificFilterConfig* maybe_filter_config{};
traversePerFilterConfigGeneric(
filter_name, route, [&maybe_filter_config](const Router::RouteSpecificFilterConfig& cfg) {
maybe_filter_config = &cfg;
});
return maybe_filter_config;
}

void Utility::traversePerFilterConfigGeneric(
const std::string& filter_name, const Router::RouteConstSharedPtr& route,
std::function<void(const Router::RouteSpecificFilterConfig&)> cb) {
Expand Down
7 changes: 4 additions & 3 deletions source/common/http/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,9 +487,10 @@ const ConfigType* resolveMostSpecificPerFilterConfig(const std::string& filter_n
const Router::RouteConstSharedPtr& route) {
static_assert(std::is_base_of<Router::RouteSpecificFilterConfig, ConfigType>::value,
"ConfigType must be a subclass of Router::RouteSpecificFilterConfig");
const Router::RouteSpecificFilterConfig* generic_config =
resolveMostSpecificPerFilterConfigGeneric(filter_name, route);
return dynamic_cast<const ConfigType*>(generic_config);
if (!route || !route->routeEntry()) {
return nullptr;
}
return route->routeEntry()->mostSpecificPerFilterConfigTyped<ConfigType>(filter_name);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,8 @@ Filter::Filter(const FilterSettings& settings, const FilterStats& stats,
: settings_(settings), stats_(stats), sigv4_signer_(sigv4_signer) {}

absl::optional<FilterSettings> Filter::getRouteSpecificSettings() const {
if (!decoder_callbacks_->route() || !decoder_callbacks_->route()->routeEntry()) {
return absl::nullopt;
}
const auto* route_entry = decoder_callbacks_->route()->routeEntry();
const auto* settings = route_entry->mostSpecificPerFilterConfigTyped<FilterSettings>(
HttpFilterNames::get().AwsLambda);
const auto* settings = Http::Utility::resolveMostSpecificPerFilterConfig<FilterSettings>(
HttpFilterNames::get().AwsLambda, decoder_callbacks_->route());
if (!settings) {
return absl::nullopt;
}
Expand Down
11 changes: 2 additions & 9 deletions source/extensions/filters/http/buffer/buffer_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,10 @@ BufferFilter::BufferFilter(BufferFilterConfigSharedPtr config)
void BufferFilter::initConfig() {
ASSERT(!config_initialized_);
config_initialized_ = true;

settings_ = config_->settings();

if (!callbacks_->route() || !callbacks_->route()->routeEntry()) {
return;
}

const std::string& name = HttpFilterNames::get().Buffer;
const auto* entry = callbacks_->route()->routeEntry();
const auto* route_local = entry->mostSpecificPerFilterConfigTyped<BufferFilterSettings>(name);

const auto* route_local = Http::Utility::resolveMostSpecificPerFilterConfig<BufferFilterSettings>(
HttpFilterNames::get().Buffer, callbacks_->route());
settings_ = route_local ? route_local : settings_;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ envoy_cc_library(
hdrs = ["proxy_filter.h"],
deps = [
"//include/envoy/http:filter_interface",
"//source/common/http:header_utility_lib",
"//source/extensions/clusters:well_known_names",
"//source/extensions/common/dynamic_forward_proxy:dns_cache_interface",
"//source/extensions/filters/http:well_known_names",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "envoy/config/core/v3/base.pb.h"
#include "envoy/extensions/filters/http/dynamic_forward_proxy/v3/dynamic_forward_proxy.pb.h"

#include "common/http/utility.h"

#include "extensions/clusters/well_known_names.h"
#include "extensions/common/dynamic_forward_proxy/dns_cache.h"
#include "extensions/filters/http/well_known_names.h"
Expand Down Expand Up @@ -87,8 +89,9 @@ Http::FilterHeadersStatus ProxyFilter::decodeHeaders(Http::RequestHeaderMap& hea
}

// Check for per route filter config.
const auto* config = route_entry->mostSpecificPerFilterConfigTyped<ProxyPerRouteConfig>(
HttpFilterNames::get().DynamicForwardProxy);
const auto* config = Http::Utility::resolveMostSpecificPerFilterConfig<ProxyPerRouteConfig>(
HttpFilterNames::get().DynamicForwardProxy, route);

if (config != nullptr) {
const auto& host_rewrite = config->hostRewrite();
if (!host_rewrite.empty()) {
Expand Down
11 changes: 3 additions & 8 deletions source/extensions/filters/http/fault/fault_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,9 @@ Http::FilterHeadersStatus FaultFilter::decodeHeaders(Http::RequestHeaderMap& hea
// faults. In other words, runtime is supported only when faults are
// configured at the filter level.
fault_settings_ = config_->settings();
if (decoder_callbacks_->route() && decoder_callbacks_->route()->routeEntry()) {
const std::string& name = Extensions::HttpFilters::HttpFilterNames::get().Fault;
const auto* route_entry = decoder_callbacks_->route()->routeEntry();

const auto* per_route_settings =
route_entry->mostSpecificPerFilterConfigTyped<FaultSettings>(name);
fault_settings_ = per_route_settings ? per_route_settings : fault_settings_;
}
const auto* per_route_settings = Http::Utility::resolveMostSpecificPerFilterConfig<FaultSettings>(
Extensions::HttpFilters::HttpFilterNames::get().Fault, decoder_callbacks_->route());
fault_settings_ = per_route_settings ? per_route_settings : fault_settings_;

if (!matchesTargetUpstreamCluster()) {
return Http::FilterHeadersStatus::Continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,14 +419,8 @@ JsonTranscoderConfig::translateProtoMessageToJson(const Protobuf::Message& messa
JsonTranscoderFilter::JsonTranscoderFilter(JsonTranscoderConfig& config) : config_(config) {}

void JsonTranscoderFilter::initPerRouteConfig() {
if (!decoder_callbacks_->route() || !decoder_callbacks_->route()->routeEntry()) {
per_route_config_ = &config_;
return;
}

const std::string& name = HttpFilterNames::get().GrpcJsonTranscoder;
const auto* entry = decoder_callbacks_->route()->routeEntry();
const auto* route_local = entry->mostSpecificPerFilterConfigTyped<JsonTranscoderConfig>(name);
const auto* route_local = Http::Utility::resolveMostSpecificPerFilterConfig<JsonTranscoderConfig>(
HttpFilterNames::get().GrpcJsonTranscoder, decoder_callbacks_->route());

per_route_config_ = route_local ? route_local : &config_;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,14 @@ Http::FilterHeadersStatus KillRequestFilter::decodeHeaders(Http::RequestHeaderMa
}

// Route-level configuration overrides filter-level configuration.
if (decoder_callbacks_->route() && decoder_callbacks_->route()->routeEntry()) {
const std::string& name = Extensions::HttpFilters::HttpFilterNames::get().KillRequest;
const auto* route_entry = decoder_callbacks_->route()->routeEntry();

const auto* per_route_kill_settings =
route_entry->mostSpecificPerFilterConfigTyped<KillSettings>(name);

if (per_route_kill_settings) {
is_correct_direction = per_route_kill_settings->getDirection() == KillRequest::REQUEST;
envoy::type::v3::FractionalPercent probability = per_route_kill_settings->getProbability();
kill_request_.set_allocated_probability(&probability);
}
const auto* per_route_kill_settings =
Http::Utility::resolveMostSpecificPerFilterConfig<KillSettings>(
Extensions::HttpFilters::HttpFilterNames::get().KillRequest, decoder_callbacks_->route());

if (per_route_kill_settings) {
is_correct_direction = per_route_kill_settings->getDirection() == KillRequest::REQUEST;
envoy::type::v3::FractionalPercent probability = per_route_kill_settings->getProbability();
kill_request_.set_allocated_probability(&probability);
}

if (is_kill_request && is_correct_direction && isKillRequestEnabled()) {
Expand Down
11 changes: 2 additions & 9 deletions source/extensions/filters/http/rbac/rbac_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,8 @@ RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig(
const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl*
RoleBasedAccessControlFilterConfig::engine(const Router::RouteConstSharedPtr route,
Filters::Common::RBAC::EnforcementMode mode) const {
if (!route || !route->routeEntry()) {
return engine(mode);
}

const std::string& name = HttpFilterNames::get().Rbac;
const auto* entry = route->routeEntry();
const auto* route_local =
entry->mostSpecificPerFilterConfigTyped<RoleBasedAccessControlRouteSpecificFilterConfig>(
name);
const auto* route_local = Http::Utility::resolveMostSpecificPerFilterConfig<
RoleBasedAccessControlRouteSpecificFilterConfig>(HttpFilterNames::get().Rbac, route);

if (route_local) {
return route_local->engine(mode);
Expand Down
51 changes: 15 additions & 36 deletions test/common/http/utility_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -872,67 +872,46 @@ TEST(HttpUtility, ResetReasonToString) {
Utility::resetReasonToString(Http::StreamResetReason::ConnectError));
}

// Verify that it resolveMostSpecificPerFilterConfigGeneric works with nil routes.
TEST(HttpUtility, ResolveMostSpecificPerFilterConfigNilRoute) {
EXPECT_EQ(nullptr, Utility::resolveMostSpecificPerFilterConfigGeneric("envoy.filter", nullptr));
}

class TestConfig : public Router::RouteSpecificFilterConfig {
public:
int state_;
void merge(const TestConfig& other) { state_ += other.state_; }
};

// Verify that resolveMostSpecificPerFilterConfig works and we get back the original type.
TEST(HttpUtility, ResolveMostSpecificPerFilterConfig) {
TestConfig testConfig;

const std::string filter_name = "envoy.filter";
NiceMock<Http::MockStreamDecoderFilterCallbacks> filter_callbacks;

// make the file callbacks return our test config
ON_CALL(*filter_callbacks.route_, perFilterConfig(filter_name))
.WillByDefault(Return(&testConfig));

// test the we get the same object back (as this goes through the dynamic_cast)
auto resolved_filter_config = Utility::resolveMostSpecificPerFilterConfig<TestConfig>(
filter_name, filter_callbacks.route());
EXPECT_EQ(&testConfig, resolved_filter_config);
// Verify that it resolveMostSpecificPerFilterConfig works with nil routes.
TEST(HttpUtility, ResolveMostSpecificPerFilterConfigNilRoute) {
EXPECT_EQ(nullptr,
Utility::resolveMostSpecificPerFilterConfig<TestConfig>("envoy.filter", nullptr));
}

// Verify that resolveMostSpecificPerFilterConfigGeneric indeed returns the most specific per
// Verify that resolveMostSpecificPerFilterConfig indeed returns the most specific per
// filter config.
TEST(HttpUtility, ResolveMostSpecificPerFilterConfigGeneric) {
TEST(HttpUtility, ResolveMostSpecificPerFilterConfig) {
const std::string filter_name = "envoy.filter";
NiceMock<Http::MockStreamDecoderFilterCallbacks> filter_callbacks;

const Router::RouteSpecificFilterConfig one;
const Router::RouteSpecificFilterConfig two;
const Router::RouteSpecificFilterConfig three;

// Test when there's nothing on the route
EXPECT_EQ(nullptr, Utility::resolveMostSpecificPerFilterConfigGeneric(filter_name,
filter_callbacks.route()));
EXPECT_EQ(nullptr, Utility::resolveMostSpecificPerFilterConfig<Router::RouteSpecificFilterConfig>(
filter_name, filter_callbacks.route()));

// Testing in reverse order, so that the method always returns the last object.
ON_CALL(filter_callbacks.route_->route_entry_.virtual_host_, perFilterConfig(filter_name))
.WillByDefault(Return(&one));
EXPECT_EQ(&one, Utility::resolveMostSpecificPerFilterConfigGeneric(filter_name,
filter_callbacks.route()));

ON_CALL(*filter_callbacks.route_, perFilterConfig(filter_name)).WillByDefault(Return(&two));
EXPECT_EQ(&two, Utility::resolveMostSpecificPerFilterConfigGeneric(filter_name,
filter_callbacks.route()));
EXPECT_EQ(&one, Utility::resolveMostSpecificPerFilterConfig<Router::RouteSpecificFilterConfig>(
filter_name, filter_callbacks.route()));

ON_CALL(filter_callbacks.route_->route_entry_, perFilterConfig(filter_name))
.WillByDefault(Return(&three));
EXPECT_EQ(&three, Utility::resolveMostSpecificPerFilterConfigGeneric(filter_name,
filter_callbacks.route()));
.WillByDefault(Return(&two));
EXPECT_EQ(&two, Utility::resolveMostSpecificPerFilterConfig<Router::RouteSpecificFilterConfig>(
filter_name, filter_callbacks.route()));

// Cover the case of no route entry
ON_CALL(*filter_callbacks.route_, routeEntry()).WillByDefault(Return(nullptr));
EXPECT_EQ(&two, Utility::resolveMostSpecificPerFilterConfigGeneric(filter_name,
filter_callbacks.route()));
EXPECT_EQ(nullptr, Utility::resolveMostSpecificPerFilterConfig<Router::RouteSpecificFilterConfig>(
filter_name, filter_callbacks.route()));
}

// Verify that traversePerFilterConfigGeneric traverses in the order of specificity.
Expand Down