rate-limit
plugin restricts maximum number of requests per entity (client or resource) in time periods.
{
"rules": [
{
"default": {
"targetHost": "example.com",
"targetPort": 80
},
"endpoints": [
{
"method": "POST",
"pathPattern": "/calculate",
"requestPlugins": [
{
"name": "rate-limit",
"conf": {
"counterName": "calculate",
"identifier": "$headers.API-KEY",
"perHour": 1000,
"perSecond": 10
}
}
]
}
]
}
]
}
Configuration attributes:
Name | Description |
---|---|
counterName | counter name |
identifier | limited entity identifier (client or resource) |
perHour | max number of calls per entity in 1 hour |
perMinute | max number of calls per entity in 1 minute |
perSecond | max number of calls per entity in 1 second |
rate-limit
plugin uses counters to aggregate requests. By defining counterName
in the configuration, all the requests to the rule endpoint
will be aggregated by that counter. Counters can be shared between endpoints. The plugin can be used to restrict access to a group of endpoints exposing the same functionality.
Example:
We have 2 methods of ingesting logs: via mobile or web. We want to limit the rate of logging requests (regardless method) to 10 per second.
The client identifies itself with a key sent in APP-KEY
header.
{
"rules": [
{
"default": {
"targetHost": "example.com",
"targetPort": 80
},
"endpoints": [
{
"method": "POST",
"pathPattern": "/log/mobile",
"requestPlugins": [
{
"name": "rate-limit",
"conf": {
"counterName": "log",
"identifier": "$headers.APP-KEY",
"perSecond": 10
}
}
]
},
{
"method": "POST",
"pathPattern": "/log/web",
"requestPlugins": [
{
"name": "rate-limit",
"conf": {
"counterName": "log",
"identifier": "$headers.APP-KEY",
"perSecond": 10
}
}
]
}
]
}
]
}
/log/mobile
and /log/web
share the same log
counter. Calls to either of those endpoints sum together.
If the client exceeds the period limit then Pyron responds with 429 status code and aborts call to target service.
Counters aggregates the calls against identifier. It might be the identity of the client, target resource id, header value, JSON body attribute, IP of the client, etc. If the number of requests with the same identifier exceeds the period limit then the counter raises an error and Pyron responds with 429 status code.
Supported identifiers:
Identifier | Example | Description |
---|---|---|
body | $body.username | JSON body attribute |
headers | $headers.API-KEY | header value |
authn | $authn.sub | authentication context, e.g. JWT OAuth access token payload |
pathParams | $pathParams.userId | endpoint path parameter |
Counter aggregates requests in period buckets - perSecond
, perMinute
, perHour
.
The period buckets are cleared every second/minute/hour respectively starting at rate-limit
plugin startup.
Let's suppose perHour
limit is set to 1000 and the plugin started at 14:20.
Then the client has 1000 requests available between 14:20 - 15:20, next 1000 requests between 15:20 - 16:20, etc.
Use headers
to configure the API key header name as identifier.
{
"name": "rate-limit",
"conf": {
"counterName": "some-counter",
"identifier": "$headers.X-API-KEY",
"perSecond": 10
}
}
Use headers
to configure the true client IP as identifier.
NOTE
Pyron reads client IP and puts it into proxy headers (see details).
{
"name": "rate-limit",
"conf": {
"counterName": "some-counter",
"identifier": "$headers.X-Real-IP",
"perSecond": 10
}
}
NOTE
You needauthn
plugin withoauth2
oroauth2-introspect
authentication method deployed.
First apply authn
plugin that puts content of OAuth2 JWT access token payload into authentication context and
then use access token sub
as rate-limit identifier.
{
"rules": [
{
"default": {
"targetHost": "example.com",
"targetPort": 80
},
"endpoints": [
{
"method": "POST",
"pathPattern": "/user/{userId}",
"requestPlugins": [
{
"name": "authn",
"conf": {
"methods": "oauth2",
"entities": "jwt"
}
},
{
"name": "rate-limit",
"conf": {
"counterName": "some-counter",
"identifier": "$authn.sub",
"perSecond": 10
}
}
]
}
]
}
]
}
Use pathParams
, body
or headers
to read resource identifier.
{
"rules": [
{
"default": {
"targetHost": "example.com",
"targetPort": 80
},
"endpoints": [
{
"method": "POST",
"pathPattern": "/user/{userId}",
"requestPlugins": [
{
"name": "rate-limit",
"conf": {
"counterName": "some-counter",
"identifier": "$pathParams.userId",
"perSecond": 10
}
}
]
}
]
}
]
}