Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions api/envoy/extensions/filters/http/ratelimit/v3/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ api_proto_package(
"//envoy/config/ratelimit/v3:pkg",
"//envoy/config/route/v3:pkg",
"//envoy/type/metadata/v3:pkg",
"//envoy/type/v3:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
],
)
11 changes: 10 additions & 1 deletion api/envoy/extensions/filters/http/ratelimit/v3/rate_limit.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "envoy/config/core/v3/extension.proto";
import "envoy/config/ratelimit/v3/rls.proto";
import "envoy/config/route/v3/route_components.proto";
import "envoy/type/metadata/v3/metadata.proto";
import "envoy/type/v3/http_status.proto";

import "google/protobuf/duration.proto";

Expand All @@ -23,7 +24,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// Rate limit :ref:`configuration overview <config_http_filters_rate_limit>`.
// [#extension: envoy.filters.http.ratelimit]

// [#next-free-field: 10]
// [#next-free-field: 11]
message RateLimit {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.rate_limit.v2.RateLimit";
Expand Down Expand Up @@ -111,6 +112,14 @@ message RateLimit {
// in case of rate limiting (i.e. 429 responses).
// Having this header not present potentially makes the request retriable.
bool disable_x_envoy_ratelimited_header = 9;

// This field allows for a custom HTTP response status code to the downstream client when
// the request has been rate limited.
// Defaults to 429 (TooManyRequests).
//
// .. note::
// If this is set to < 400, 429 will be used instead.
type.v3.HttpStatus status = 10;
Comment thread
htuch marked this conversation as resolved.
Outdated
Comment thread
htuch marked this conversation as resolved.
Outdated
}

// Global rate limiting :ref:`architecture overview <arch_overview_global_rate_limit>`.
Expand Down
4 changes: 2 additions & 2 deletions source/extensions/filters/http/ratelimit/ratelimit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ void Filter::complete(Filters::Common::RateLimit::LimitStatus status,
Http::CodeStats::ResponseStatInfo info{config_->scope(),
cluster_->statsScope(),
empty_stat_name,
enumToInt(Http::Code::TooManyRequests),
enumToInt(config_->status()),
true,
empty_stat_name,
empty_stat_name,
Expand Down Expand Up @@ -200,7 +200,7 @@ void Filter::complete(Filters::Common::RateLimit::LimitStatus status,
state_ = State::Responded;
callbacks_->streamInfo().setResponseFlag(StreamInfo::ResponseFlag::RateLimited);
callbacks_->sendLocalReply(
Http::Code::TooManyRequests, response_body,
config_->status(), response_body,
[this](Http::HeaderMap& headers) {
populateResponseHeaders(headers, /*from_local_reply=*/true);
},
Expand Down
13 changes: 12 additions & 1 deletion source/extensions/filters/http/ratelimit/ratelimit.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class FilterConfig {
config.rate_limited_as_resource_exhausted()
? absl::make_optional(Grpc::Status::WellKnownGrpcStatus::ResourceExhausted)
: absl::nullopt),
http_context_(http_context), stat_names_(scope.symbolTable()) {}
http_context_(http_context), stat_names_(scope.symbolTable()),
status_(toErrorCode(config.status().code())) {}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add test for those new code? Then the code LGTM.

const std::string& domain() const { return domain_; }
const LocalInfo::LocalInfo& localInfo() const { return local_info_; }
uint64_t stage() const { return stage_; }
Expand All @@ -70,6 +71,7 @@ class FilterConfig {
}
Http::Context& httpContext() { return http_context_; }
Filters::Common::RateLimit::StatNames& statNames() { return stat_names_; }
Http::Code status() { return status_; }

private:
static FilterRequestType stringToType(const std::string& request_type) {
Expand All @@ -83,6 +85,14 @@ class FilterConfig {
}
}

static Http::Code toErrorCode(uint64_t status) {
const auto code = static_cast<Http::Code>(status);
if (code >= Http::Code::BadRequest) {
return code;
}
return Http::Code::TooManyRequests;
}

const std::string domain_;
const uint64_t stage_;
const FilterRequestType request_type_;
Expand All @@ -95,6 +105,7 @@ class FilterConfig {
const absl::optional<Grpc::Status::GrpcStatus> rate_limited_grpc_status_;
Http::Context& http_context_;
Filters::Common::RateLimit::StatNames stat_names_;
const Http::Code status_;
};

using FilterConfigSharedPtr = std::shared_ptr<FilterConfig>;
Expand Down