This plugin allows you to limit the number of requests a developer can make based on a custom response header returned by the upstream service. You can arbitrary set as many rate-limiting objects (or quotas) as you want and instruct IAM to increase or decrease them by any number of units. Each custom rate-limiting object can limit the inbound requests per seconds, minutes, hours, days, months or years.
If the underlying Service/Route (or deprecated API entity) has no authentication layer, the Client IP address will be used, otherwise the Consumer will be used if an authentication plugin has been configured.
Terminology
plugin
: a plugin executing actions inside IAM before or after a request has been proxied to the upstream API.Service
: the IAM entity representing an external upstream API or microservice.Route
: the IAM entity representing a way to map downstream requests to upstream services.Consumer
: the IAM entity representing a developer or machine using the API. When using IAM, a Consumer only communicates with IAM which proxies every call to the said upstream API.Credential
: a unique string associated with a Consumer, also referred to as an API key.upstream service
: this refers to your own API/service sitting behind IAM, to which client requests are forwarded.API
: a legacy entity used to represent your upstream services. Deprecated in favor of Services.
Configuration
This plugin is compatible with requests with the following protocols:
http
https
This plugin is partially compatible with DB-less mode.
The plugin will run fine with the `local` policy (which doesn't use the database) or the `redis` policy (which uses an independent Redis, so it is compatible with DB-less). The plugin will not work with the `cluster` policy, which requires writes to the database.Enabling the plugin on a Service
With a database
Configure this plugin on a Service by making the following request:
$ curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=response-ratelimiting" \
--data "config.limits.{limit_name}=" \
--data "config.limits.{limit_name}.minute=10"
Without a database
Configure this plugin on a Service by adding this section do your declarative configuration file:
plugins:
- name: response-ratelimiting
service: {service}
config:
limits.{limit_name}:
limits.{limit_name}.minute: 10
In both cases, {service}
is the id
or name
of the Service that this plugin configuration will target.
Enabling the plugin on a Route
With a database
Configure this plugin on a Route with:
$ curl -X POST http://localhost:8001/routes/{route}/plugins \
--data "name=response-ratelimiting" \
--data "config.limits.{limit_name}=" \
--data "config.limits.{limit_name}.minute=10"
Without a database
Configure this plugin on a Route by adding this section do your declarative configuration file:
plugins:
- name: response-ratelimiting
route: {route}
config:
limits.{limit_name}:
limits.{limit_name}.minute: 10
In both cases, {route}
is the id
or name
of the Route that this plugin configuration will target.
Enabling the plugin on a Consumer
With a database
You can use the http://localhost:8001/plugins
endpoint to enable this plugin
on specific Consumers:
$ curl -X POST http://localhost:8001/consumers/{consumer}/plugins \
--data "name=response-ratelimiting" \
\
--data "config.limits.{limit_name}=" \
--data "config.limits.{limit_name}.minute=10"
Without a database
Configure this plugin on a Consumer by adding this section do your declarative configuration file:
plugins:
- name: response-ratelimiting
consumer: {consumer}
config:
limits.{limit_name}:
limits.{limit_name}.minute: 10
In both cases, {consumer}
is the id
or username
of the Consumer that this plugin configuration will target.
You can combine consumer_id
and
service_id
in the same request, to furthermore narrow the scope of the plugin.
Global plugins
- Using a database, all plugins can be configured using the
http://localhost:8001/plugins/
endpoint. - Without a database, all plugins can be configured via the
plugins:
entry on the declarative configuration file.
A plugin which is not associated to any Service, Route or Consumer (or API, if you are using an older version of IAM) is considered "global", and will be run on every request. Read the Plugin Reference and the Plugin Precedence sections for more information.
Parameters
Here's a list of all the parameters which can be used in this plugin's configuration:
form parameter | description |
---|---|
name | The name of the plugin to use, in this case response-ratelimiting |
service_id | The id of the Service which this plugin will target. |
route_id | The id of the Route which this plugin will target. |
enabled default value: true | Whether this plugin will be applied. |
consumer_id | The id of the Consumer which this plugin will target. |
api_id | The id of the API which this plugin will target. |
config.limits.{limit_name}
|
This is a list of custom objects that you can set, with arbitrary names set in the |
config.limits.{limit_name}.second
semi-optional |
The amount of HTTP requests the developer can make per second. At least one limit must exist. |
config.limits.{limit_name}.minute
semi-optional |
The amount of HTTP requests the developer can make per minute. At least one limit must exist. |
config.limits.{limit_name}.hour
semi-optional |
The amount of HTTP requests the developer can make per hour. At least one limit must exist. |
config.limits.{limit_name}.day
semi-optional |
The amount of HTTP requests the developer can make per day. At least one limit must exist. |
config.limits.{limit_name}.month
semi-optional |
The amount of HTTP requests the developer can make per month. At least one limit must exist. |
config.limits.{limit_name}.year
semi-optional |
The amount of HTTP requests the developer can make per year. At least one limit must exist. |
config.header_name
optional default value:
|
The name of the response header used to increment the counters. |
config.block_on_first_violation
optional default value:
|
A boolean value that determines if the requests should be blocked as soon as one limit is being exceeded. This will block requests that are supposed to consume other limits too. |
config.limit_by
optional default value:
|
The entity that will be used when aggregating the limits: |
config.policy
optional default value:
|
The rate-limiting policies to use for retrieving and incrementing the limits. Available values are |
config.fault_tolerant
optional default value:
|
A boolean value that determines if the requests should be proxied even if IAM has troubles connecting a third-party datastore. If |
config.hide_client_headers
optional default value:
|
Optionally hide informative response headers. |
config.redis_host
semi-optional |
When using the |
config.redis_port
optional default value:
|
When using the |
config.redis_password
optional |
When using the |
config.redis_timeout
optional default value:
|
When using the |
config.redis_database
optional default value:
|
When using the |
Configuring Quotas
After adding the plugin, you can increment the configured limits by adding the following response header:
Header-Name: Limit=Value [,Limit=Value]
Since X-Kong-Limit
is the default header name (you can optionally change it), it will look like:
X-Kong-Limit: limitname1=2, limitname2=4
That will increment the limit limitname1
by 2 units, and limitname2
by 4 units.
You can optionally increment more than one limit by comma separating the entries. The header will be removed before returning the response to the original client.
Headers sent to the client
When this plugin is enabled, IAM will send some additional headers back to the client telling how many units are available and how many are allowed. For example if you created a limit/quota called “Videos” with a per-minute limit:
X-RateLimit-Limit-Videos-Minute: 10
X-RateLimit-Remaining-Videos-Minute: 9
or it will return a combination of more time limits, if more than one is being set:
X-RateLimit-Limit-Videos-Second: 5
X-RateLimit-Remaining-Videos-Second: 5
X-RateLimit-Limit-Videos-Minute: 10
X-RateLimit-Remaining-Videos-Minute: 10
If any of the limits configured is being reached, the plugin will return a HTTP/1.1 429
status code and an empty body.
Upstream Headers
The plugin will append the usage headers for each limit before proxying it to the upstream service, so that you can properly refuse to process the request if there are no more limits remaining. The headers are in the form of X-RateLimit-Remaining-{limit_name}
, like:
X-RateLimit-Remaining-Videos: 3
X-RateLimit-Remaining-Images: 0