Limit one client wherever it calls
A limit on a route counts every client that calls that route. A limit on a consumer counts one client, on every route it calls with its key. This guide gives the mobile app 600 requests a minute, whatever route it calls. At the end, every answer to the app carries a limit header on each route that asks for its key, and the next request after the 600th in a window is answered 429.
Before you start
- This guide starts from
orders-apias Route requests to a backend leaves it, with key-auth from Require an API key. The requests below call/orders/42onorders-apiand/invoices/7oninvoices-api. A plugin from another guide that this page does not name can change the answers below; remove it first or work on a copy of the route. - A second route,
invoices-api, created as Route requests to a backend shows. Give it the nameinvoices-api, the paths/invoicesand/invoices/*, the same backend nodes10.0.1.10:8080and10.0.1.11:8080, and key-auth as onorders-api. - The consumer and its key. This guide uses
mobile-app, created in Require an API key. To read its key back, see Give a client its key. - The host name of your gateway. In the console it is the first part of the Address line on a route's Overview tab,
api.example.comin this page's examples; replace it in every request below. - The Editor or Environment administrator role in this environment. A Viewer sees the Plugins tab but has no Add plugin button.
Steps
1. Open the consumer's Plugins tab
Open mobile-app under Consumers, select its Plugins tab, then Add plugin at the top right of the tab. The picker offers no authentication plugin here, because a consumer signs in with its credentials, not with a plugin of its own.
2. Choose limit-count
Open the Traffic category, or type limit-count in the search box. Select limit-count, then Configure.
3. Fill in the limit
The form has three sections, Basics, Behavior and Advanced. Under Basics, One limit for everything here is already chosen. Keep it. Fill in these four fields and leave every other field as it is.
| Field | Value | Why |
|---|---|---|
| Count | 600 | Requests allowed in one window. |
| Time window | 60 | The window, in seconds. 600 in 60 seconds is 600 a minute. |
| Key | consumer_name | What the requests are counted by. On a consumer, count by the consumer's name. The default, remote_addr, would count each client address separately. |
| Rejected code, under Behavior | 429 | The status a refused request gets. Unset, the gateway answers 503 with an HTML error page. |
Select Add plugin at the bottom of the panel. The tab lists limit-count, and the consumer is saved like this:
{
"username": "mobile-app",
"desc": "The iOS and Android apps, which call under one consumer name",
"labels": {
"team": "mobile"
},
"plugins": {
"limit-count": {
"count": 600,
"time_window": 60,
"key": "consumer_name",
"rejected_code": 429
}
}
}
The example consumer also carries the desc typed when it was created and labels set by other guides, Allow a team by label among them. Yours may not carry them. Neither plays a part in the limit.
Check it
Send a request with the app's key to orders-api, then to invoices-api, then a request without a key. The key goes in the x-api-key header, where key-auth on the route reads it.
curl -i -L 'https://<gateway host>/orders/42' \
-H 'x-api-key: <the key of mobile-app>'
- First request
- A request with the key of mobile-app is answered
200withX-RateLimit-Limit: 600: the consumer's own limit-count counts it, though the route carries no limit of its own. - Second route
- The same key on a second route that asks for it is counted in the same 600: after one request on each route, the answer carries
X-RateLimit-Remaining: 598. - At the backend
- Your backend receives the request with the consumer's username in
X-Consumer-Username. - No key
- A request without a key is answered
401with{"message":"Missing API key in request"}.
To see the refusal, send the request 600 times in one minute, in a shell loop for example. The 601st answer within the window is 429. Its headers carry X-RateLimit-Remaining: 0 and X-RateLimit-Reset with the seconds until the window ends. The body is the gateway's own error page, since this example sets no Rejected message.
To take the limit off again, go to the consumer's Plugins tab. Open the actions menu at the right of the limit-count row and select Remove. Confirm with Remove plugin.
What to know
- The count is one count for the consumer. A request on
orders-apiand a request oninvoices-apiboth draw on the same 600. - Each gateway node keeps its own count unless Policy, under Behavior, points at Redis. With two nodes and the default policy, the app can get 600 on each. Limit requests on a route shows the Redis setup.
- Where the route carries limit-count too, the consumer's copy counts and the route's does not. A consumer with 2000 on a route whose own limit is 100 is counted by its 2000.
- The window opens with the consumer's first request and lasts 60 seconds from then. It does not follow the clock, so a count that starts mid-minute still gets a full window.
- A limit on the consumer needs a plugin on the route that names the consumer, usually key-auth. On a route without one, the consumer is never identified and its limit never runs.
Related
- Limit requests on a route: one limit for every client of a route, counted by client address.
- Give a group of clients one limit: the same limit for every consumer in a group.
- Consumer and limit-count in the reference.