Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lua: add a new clear_route_cache option support #38514

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions api/envoy/extensions/filters/http/lua/v3/lua.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package envoy.extensions.filters.http.lua.v3;

import "envoy/config/core/v3/base.proto";

import "google/protobuf/wrappers.proto";

import "envoy/annotations/deprecation.proto";
import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";
Expand All @@ -19,6 +21,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// Lua :ref:`configuration overview <config_http_filters_lua>`.
// [#extension: envoy.filters.http.lua]

// [#next-free-field: 6]
message Lua {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.lua.v2.Lua";
Expand Down Expand Up @@ -78,6 +81,12 @@ message Lua {
// stat_prefix: bar_script # This emits lua.bar_script.errors etc.
//
string stat_prefix = 4;

// If set to true, the Lua filter will clear the route cache automatically if the request
// headers are modified by the Lua script. If set to false, the Lua filter will not clear the
// route cache automatically.
// Default is true for backward compatibility.
google.protobuf.BoolValue clear_route_cache = 5;
}

message LuaPerRoute {
Expand Down
5 changes: 5 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ new_features:
change: |
Made the :ref:`credential injector filter <envoy_v3_api_msg_extensions.filters.http.credential_injector.v3.CredentialInjector>`
work as an upstream filter.
- area: lua
change: |
Added :ref:`clear_route_cache <envoy_v3_api_field_extensions.filters.http.lua.v3.Lua.clear_route_cache>` support to
control the route cache clearing behavior in the Lua filter.

- area: tcp_proxy
change: |
added :ref:`an option <config_network_filters_tcp_proxy_receive_before_connect>` to allow filters to read from the
Expand Down
2 changes: 2 additions & 0 deletions source/extensions/filters/http/lua/lua_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,8 @@ FilterConfig::FilterConfig(const envoy::extensions::filters::http::lua::v3::Lua&
Upstream::ClusterManager& cluster_manager, Api::Api& api,
Stats::Scope& scope, const std::string& stats_prefix)
: cluster_manager_(cluster_manager),
clear_route_cache_(
proto_config.has_clear_route_cache() ? proto_config.clear_route_cache().value() : true),
stats_(generateStats(stats_prefix, proto_config.stat_prefix(), scope)) {
if (proto_config.has_default_source_code()) {
if (!proto_config.inline_code().empty()) {
Expand Down
11 changes: 10 additions & 1 deletion source/extensions/filters/http/lua/lua_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ class FilterConfig : Logger::Loggable<Logger::Id::lua> {
}
return nullptr;
}
bool clearRouteCache() const { return clear_route_cache_; }

const LuaFilterStats& stats() const { return stats_; }

Expand All @@ -417,6 +418,7 @@ class FilterConfig : Logger::Loggable<Logger::Id::lua> {
return {ALL_LUA_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix))};
}

const bool clear_route_cache_{};
PerLuaCodeSetupPtr default_lua_code_setup_;
absl::flat_hash_map<std::string, PerLuaCodeSetupPtr> per_lua_code_setups_map_;
LuaFilterStats stats_;
Expand Down Expand Up @@ -536,7 +538,14 @@ class Filter : public Http::StreamFilter, private Filters::Common::Lua::LuaLogga
}
const Buffer::Instance* bufferedBody() override { return callbacks_->decodingBuffer(); }
void continueIteration() override { return callbacks_->continueDecoding(); }
void onHeadersModified() override { callbacks_->downstreamCallbacks()->clearRouteCache(); }
void onHeadersModified() override {
// Do not clear route cache if clear_route_cache is false or if no downstream callbacks are
// available.
if (!parent_.config_->clearRouteCache() || !callbacks_->downstreamCallbacks()) {
return;
}
callbacks_->downstreamCallbacks()->clearRouteCache();
}
void respond(Http::ResponseHeaderMapPtr&& headers, Buffer::Instance* body,
lua_State* state) override;

Expand Down
24 changes: 22 additions & 2 deletions test/extensions/filters/http/lua/lua_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ class LuaHttpFilterTest : public testing::Test {
setupFilter();
}

void setupConfig(envoy::extensions::filters::http::lua::v3::Lua& proto_config,
envoy::extensions::filters::http::lua::v3::LuaPerRoute& per_route_proto_config) {
void setupConfig(
const envoy::extensions::filters::http::lua::v3::Lua& proto_config,
const envoy::extensions::filters::http::lua::v3::LuaPerRoute& per_route_proto_config) {
// Setup filter config for Lua filter.
config_ = std::make_shared<FilterConfig>(proto_config, tls_, cluster_manager_, api_,
*stats_store_.rootScope(), "test.");
Expand Down Expand Up @@ -2735,6 +2736,25 @@ TEST_F(LuaHttpFilterTest, LuaFilterDisabled) {
EXPECT_FALSE(request_headers_2.has("hello"));
}

// Test whether the automatic route cache clearing could be disabled.
TEST_F(LuaHttpFilterTest, DisableAutomaticRouteCacheClearing) {
envoy::extensions::filters::http::lua::v3::Lua proto_config;
proto_config.mutable_clear_route_cache()->set_value(false);
proto_config.mutable_default_source_code()->set_inline_string(ADD_HEADERS_SCRIPT);
setupConfig(proto_config, {});
setupFilter();

EXPECT_CALL(decoder_callbacks_.downstream_callbacks_, clearRouteCache()).Times(0);

ON_CALL(*decoder_callbacks_.route_, mostSpecificPerFilterConfig(_))
.WillByDefault(Return(nullptr));

Http::TestRequestHeaderMapImpl request_headers_1{{":path", "/"}};

EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers_1, true));
EXPECT_EQ("world", request_headers_1.get_("hello"));
}

// Test whether the route can directly reuse the Lua code in the global configuration.
TEST_F(LuaHttpFilterTest, LuaFilterRefSourceCodes) {
const std::string SCRIPT_FOR_ROUTE_ONE{R"EOF(
Expand Down
Loading