syntax = "proto3";

package envoy.extensions.filters.http.local_ratelimit.v3;

import "envoy/config/core/v3/base.proto";
import "envoy/extensions/common/ratelimit/v3/ratelimit.proto";
import "envoy/type/v3/http_status.proto";
import "envoy/type/v3/token_bucket.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.filters.http.local_ratelimit.v3";
option java_outer_classname = "LocalRateLimitProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/local_ratelimit/v3;local_ratelimitv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Local Rate limit]
// Local Rate limit :ref:`configuration overview <config_http_filters_local_rate_limit>`.
// [#extension: envoy.filters.http.local_ratelimit]

// [#next-free-field: 13]
message LocalRateLimit {
  // The human readable prefix to use when emitting stats.
  string stat_prefix = 1 [(validate.rules).string = {min_len: 1}];

  // 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 = 2;

  // The token bucket configuration to use for rate limiting requests that are processed by this
  // filter. Each request processed by the filter consumes a single token. If the token is available,
  // the request will be allowed. If no tokens are available, the request will receive the configured
  // rate limit status.
  //
  // .. note::
  //   It's fine for the token bucket to be unset for the global configuration since the rate limit
  //   can be applied at a the virtual host or route level. Thus, the token bucket must be set
  //   for the per route configuration otherwise the config will be rejected.
  //
  // .. note::
  //   When using per route configuration, the bucket becomes unique to that route.
  //
  // .. note::
  //   In the current implementation the token bucket's :ref:`fill_interval
  //   <envoy_v3_api_field_type.v3.TokenBucket.fill_interval>` must be >= 50ms to avoid too aggressive
  //   refills.
  type.v3.TokenBucket token_bucket = 3;

  // If set, this will enable -- but not necessarily enforce -- the rate limit for the given
  // fraction of requests.
  // Defaults to 0% of requests for safety.
  config.core.v3.RuntimeFractionalPercent filter_enabled = 4;

  // If set, this will enforce the rate limit decisions for the given fraction of requests.
  //
  // Note: this only applies to the fraction of enabled requests.
  //
  // Defaults to 0% of requests for safety.
  config.core.v3.RuntimeFractionalPercent filter_enforced = 5;

  // Specifies a list of HTTP headers that should be added to each request that
  // has been rate limited and is also forwarded upstream. This can only occur when the
  // filter is enabled but not enforced.
  repeated config.core.v3.HeaderValueOption request_headers_to_add_when_not_enforced = 10
      [(validate.rules).repeated = {max_items: 10}];

  // Specifies a list of HTTP headers that should be added to each response for requests that
  // have been rate limited. This occurs when the filter is either enabled or fully enforced.
  repeated config.core.v3.HeaderValueOption response_headers_to_add = 6
      [(validate.rules).repeated = {max_items: 10}];

  // The rate limit descriptor list to use in the local rate limit to override
  // on. The rate limit descriptor is selected by the first full match from the
  // request descriptors.
  //
  // Example on how to use ::ref:`this <config_http_filters_local_rate_limit_descriptors>`
  //
  // .. note::
  //
  //   In the current implementation the descriptor's token bucket :ref:`fill_interval
  //   <envoy_v3_api_field_type.v3.TokenBucket.fill_interval>` must be a multiple
  //   global :ref:`token bucket's<envoy_v3_api_field_extensions.filters.http.local_ratelimit.v3.LocalRateLimit.token_bucket>` fill interval.
  //
  //   The descriptors must match verbatim for rate limiting to apply. There is no partial
  //   match by a subset of descriptor entries in the current implementation.
  repeated common.ratelimit.v3.LocalRateLimitDescriptor descriptors = 8;

  // Specifies the rate limit configurations to be applied with the same
  // stage number. If not set, the default stage number is 0.
  //
  // .. note::
  //
  //  The filter supports a range of 0 - 10 inclusively for stage numbers.
  uint32 stage = 9 [(validate.rules).uint32 = {lte: 10}];

  // Specifies the scope of the rate limiter's token bucket.
  // If set to false, the token bucket is shared across all worker threads,
  // thus the rate limits are applied per Envoy process.
  // If set to true, a token bucket is allocated for each connection.
  // Thus the rate limits are applied per connection thereby allowing
  // one to rate limit requests on a per connection basis.
  // If unspecified, the default value is false.
  bool local_rate_limit_per_downstream_connection = 11;

  // Defines the standard version to use for X-RateLimit headers emitted by the filter.
  //
  // Disabled by default.
  common.ratelimit.v3.XRateLimitHeadersRFCVersion enable_x_ratelimit_headers = 12
      [(validate.rules).enum = {defined_only: true}];
}
