@@ -131,6 +131,24 @@ class HttpRateLimitFilterTest : public testing::Test {
131
131
stat_prefix: with_stat_prefix
132
132
)EOF" ;
133
133
134
+ const std::string filter_config_with_filter_enabled_ = R"EOF(
135
+ domain: foo
136
+ filter_enabled:
137
+ runtime_key: test_enabled
138
+ default_value:
139
+ numerator: 30
140
+ denominator: HUNDRED
141
+ )EOF" ;
142
+
143
+ const std::string filter_config_with_filter_enforced_ = R"EOF(
144
+ domain: foo
145
+ filter_enforced:
146
+ runtime_key: test_enforced
147
+ default_value:
148
+ numerator: 50
149
+ denominator: HUNDRED
150
+ )EOF" ;
151
+
134
152
Filters::Common::RateLimit::MockClient* client_;
135
153
NiceMock<Http::MockStreamDecoderFilterCallbacks> filter_callbacks_;
136
154
Stats::StatNamePool pool_{filter_callbacks_.clusterInfo ()->statsScope ().symbolTable ()};
@@ -233,6 +251,29 @@ TEST_F(HttpRateLimitFilterTest, RuntimeDisabled) {
233
251
EXPECT_EQ (Http::FilterTrailersStatus::Continue, filter_->encodeTrailers (response_trailers_));
234
252
}
235
253
254
+ TEST_F (HttpRateLimitFilterTest, RuntimeDisabledFromFilterConfig) {
255
+ setUpTest (filter_config_with_filter_enabled_);
256
+
257
+ EXPECT_CALL (
258
+ factory_context_.runtime_loader_ .snapshot_ ,
259
+ featureEnabled (absl::string_view (" test_enabled" ),
260
+ testing::Matcher<const envoy::type::v3::FractionalPercent&>(Percent (30 ))))
261
+ .WillOnce (testing::Return (false ));
262
+
263
+ // Explicit configuration in the filter config should override the default runtime key.
264
+ EXPECT_CALL (factory_context_.runtime_loader_ .snapshot_ ,
265
+ featureEnabled (" ratelimit.http_filter_enabled" , 100 ))
266
+ .Times (0 );
267
+
268
+ EXPECT_EQ (Http::FilterHeadersStatus::Continue, filter_->decodeHeaders (request_headers_, false ));
269
+ EXPECT_EQ (Http::FilterDataStatus::Continue, filter_->decodeData (data_, false ));
270
+ EXPECT_EQ (Http::FilterTrailersStatus::Continue, filter_->decodeTrailers (request_trailers_));
271
+ EXPECT_EQ (Http::Filter1xxHeadersStatus::Continue, filter_->encode1xxHeaders (response_headers_));
272
+ EXPECT_EQ (Http::FilterHeadersStatus::Continue, filter_->encodeHeaders (response_headers_, false ));
273
+ EXPECT_EQ (Http::FilterDataStatus::Continue, filter_->encodeData (response_data_, false ));
274
+ EXPECT_EQ (Http::FilterTrailersStatus::Continue, filter_->encodeTrailers (response_trailers_));
275
+ }
276
+
236
277
TEST_F (HttpRateLimitFilterTest, OkResponse) {
237
278
setUpTest (filter_config_);
238
279
InSequence s;
@@ -1043,6 +1084,56 @@ TEST_F(HttpRateLimitFilterTest, LimitResponseRuntimeDisabled) {
1043
1084
filter_callbacks_.clusterInfo ()->statsScope ().counterFromStatName (upstream_rq_429_).value ());
1044
1085
}
1045
1086
1087
+ TEST_F (HttpRateLimitFilterTest, LimitResponseRuntimeDisabledFromFilterConfig) {
1088
+ setUpTest (filter_config_with_filter_enforced_);
1089
+ InSequence s;
1090
+
1091
+ EXPECT_CALL (route_rate_limit_, populateDescriptors (_, _, _, _))
1092
+ .WillOnce (SetArgReferee<0 >(descriptor_));
1093
+ EXPECT_CALL (*client_, limit (_, _, _, _, _, 0 ))
1094
+ .WillOnce (
1095
+ WithArgs<0 >(Invoke ([&](Filters::Common::RateLimit::RequestCallbacks& callbacks) -> void {
1096
+ request_callbacks_ = &callbacks;
1097
+ })));
1098
+
1099
+ EXPECT_EQ (Http::FilterHeadersStatus::StopIteration,
1100
+ filter_->decodeHeaders (request_headers_, false ));
1101
+
1102
+ EXPECT_CALL (
1103
+ factory_context_.runtime_loader_ .snapshot_ ,
1104
+ featureEnabled (absl::string_view (" test_enforced" ),
1105
+ testing::Matcher<const envoy::type::v3::FractionalPercent&>(Percent (50 ))))
1106
+ .WillOnce (testing::Return (false ));
1107
+
1108
+ // Explicit configuration in the filter config should override the default runtime key.
1109
+ EXPECT_CALL (factory_context_.runtime_loader_ .snapshot_ ,
1110
+ featureEnabled (" ratelimit.http_filter_enforcing" , 100 ))
1111
+ .Times (0 );
1112
+
1113
+ EXPECT_CALL (filter_callbacks_, continueDecoding ());
1114
+ Http::ResponseHeaderMapPtr h{new Http::TestResponseHeaderMapImpl ()};
1115
+ request_callbacks_->complete (Filters::Common::RateLimit::LimitStatus::OverLimit, nullptr ,
1116
+ std::move (h), nullptr , " " , nullptr );
1117
+
1118
+ EXPECT_EQ (Http::FilterDataStatus::Continue, filter_->decodeData (data_, false ));
1119
+ EXPECT_EQ (Http::FilterTrailersStatus::Continue, filter_->decodeTrailers (request_trailers_));
1120
+ EXPECT_EQ (Http::Filter1xxHeadersStatus::Continue, filter_->encode1xxHeaders (response_headers_));
1121
+ EXPECT_EQ (Http::FilterHeadersStatus::Continue, filter_->encodeHeaders (response_headers_, false ));
1122
+ EXPECT_EQ (Http::FilterDataStatus::Continue, filter_->encodeData (response_data_, false ));
1123
+ EXPECT_EQ (Http::FilterTrailersStatus::Continue, filter_->encodeTrailers (response_trailers_));
1124
+
1125
+ EXPECT_EQ (1U , filter_callbacks_.clusterInfo ()
1126
+ ->statsScope ()
1127
+ .counterFromStatName (ratelimit_over_limit_)
1128
+ .value ());
1129
+ EXPECT_EQ (
1130
+ 1U ,
1131
+ filter_callbacks_.clusterInfo ()->statsScope ().counterFromStatName (upstream_rq_4xx_).value ());
1132
+ EXPECT_EQ (
1133
+ 1U ,
1134
+ filter_callbacks_.clusterInfo ()->statsScope ().counterFromStatName (upstream_rq_429_).value ());
1135
+ }
1136
+
1046
1137
TEST_F (HttpRateLimitFilterTest, LimitResponseWithRateLimitedStatus) {
1047
1138
setUpTest (rate_limited_status_config_);
1048
1139
InSequence s;
0 commit comments