Apply a plugin to every request
A global rule holds plugins that run on every request the gateway of the environment handles: on every route, whatever the route carries itself, and on requests that no route takes. This guide creates a rule that gives each client 1000 requests a minute over every route, behind your load balancers. At the end, each client gets 1000 requests a minute over all the routes of the environment, counted under its own address.
Treat every plugin you add here as a change to every route at once. A plugin that refuses requests refuses them everywhere, routes meant to stay open included.
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/42. 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 plugin belongs on a global rule only when every request of the environment needs it. A plugin that only some routes need goes on those routes, on their service, or on a plugin config.
- Behind load balancers, two facts from the team that runs them: the header each client's address is written into,
X-Forwarded-Forhere, and every address the load balancers connect from,10.0.0.21and10.0.0.22here. Without a load balancer, skip step 3. - 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.
Steps
1. Look at the rules the environment already has
In the menu, select Plugins, then the Global rules tab. Rules may be there already. One runs the prometheus plugin, which makes the request counts Analytics shows. Another, g8-request-records, is the rule G8 writes for Traffic Explorer once request records are turned on, as Where request records go explains.
Leave them as they are and put your plugins in a rule of your own. A plugin can be in one global rule at a time.
2. Create a global rule of your own
Select New global rule. Under General, set ID to rate-limit-every-route, a name that says what the rule is for. It cannot be changed later. Select Create global rule. A rule without plugins changes nothing yet.
3. Add real-ip first, so that every plugin sees each client's own address
Open the rule's Plugins tab, then Add plugin at the top right of the tab. Open the General category, or type real-ip in the search box. Select real-ip, then Configure.
| Field | Value |
|---|---|
| Source | http_x_forwarded_for |
| Trusted addresses | 10.0.0.21 and 10.0.0.22; type a value and press Enter for each. List every address your load balancers connect from, and nothing else. |
| Recursive | off |
Select Add plugin at the bottom of the panel. From now on, the plugins of every route see the address real-ip took from the header, and your backends receive it in X-Real-IP. See each client's own address explains the plugin.
4. Add limit-count
Select Add plugin at the top right of the tab again. Open the Traffic category, or type limit-count in the search box. Select limit-count, then Configure.
| Field | Value |
|---|---|
| Count | 1000 |
| Time window | 60 |
| Key | remote_addr, the client address, which real-ip has now set to each client's own. |
| Rejected code, under Behavior | 429 |
Select Add plugin at the bottom of the panel. From this moment every request of the environment is counted, on every route and when no route takes it. The rule is saved like this:
{
"id": "rate-limit-every-route",
"plugins": {
"real-ip": {
"source": "http_x_forwarded_for",
"trusted_addresses": [
"10.0.0.21",
"10.0.0.22"
]
},
"limit-count": {
"count": 1000,
"time_window": 60,
"key": "remote_addr",
"rejected_code": 429
}
}
}
5. See the rule from a route
Open orders-api and its Plugins tab. Under Request path, the Global rules stage lists real-ip and limit-count above the route's own plugins. The Also applied card lists them under Global rules with the rule's ID.
Check it
Send the request through your load balancers, then from a second machine, then to a path that no route takes. key-auth is on orders-api, so add the key of mobile-app in the x-api-key header to the request below.
curl -i -L 'https://<gateway host>/orders/42'
- Through the load balancers
- The requests of every route are counted for each client, on a route with no plugins of its own as well: its answer carries
X-RateLimit-Limit: 1000. - From a second client
- Each client behind your load balancers has a count of its own: the first request of a second client also arrives with
X-RateLimit-Remaining: 999. - To a path no route takes
- A request that no route takes is counted as well, and is still answered
404. - On a route with a limit of its own
- A route with a limit-count of its own keeps it, and that copy also counts each client by its own address. Its answers show the route's numbers,
X-RateLimit-Limit: 100for example, while each of those requests is still taken from the client's 1000. - On a route that admits only the load balancers
- The route itself is matched before any plugin runs, the global rule's included: with Client addresses that leave
203.0.113.8out, its request still reaches the route through your load balancer, and your backend receivesX-Real-IP: 203.0.113.8.
The last answer comes from a route whose Client addresses leave the client at 203.0.113.8 out. The client's request still reaches it through the load balancer, because the route is matched on the load balancer's address before real-ip runs. A route's Client addresses therefore cannot keep out a client behind a load balancer.
What to know
- A route's own limit-count does not replace the global one. Both count each request: the route's answers show the route's numbers, and each request is still taken from the client's global count. A consumer's own limit does not replace it either.
- A route that keeps real-ip from See each client's own address runs it beside the global copy. Neither copy replaces the other, and the global rule's runs first, as Where a plugin runs explains.
- key-auth on a global rule answers 401 to every request without a key, on routes meant to stay open and on paths no route takes. A route that keeps key-auth of its own then refuses every valid key, because the global copy takes the key away first.
- A global limit-count with Key
consumer_namecounts each consumer apart over every route that asks for its key. The route's key-auth names the consumer before the global limit counts. - Deleting a global rule takes its plugins off every route at once.
- Analytics shows request counts only while a global rule runs the prometheus plugin. Leave that rule in place.
Related
- Where a plugin runs: global rules beside routes, services, plugin configs and consumers.
- See each client's own address: real-ip on one route instead.
- Limit requests on a route: a limit on one route alone.
- Global rule in the reference.