Hello there!,
I’ve run into a problem with setting up rate limits for my application. The main idea is to enable a global rate limit (affecting all endpoints) but being able to disable it for certain API endpoints so we can have less restrictive ones for those endpoints.
We tried creating both: a global rate limit middleware and a api rate limit middleware based on koa2-ratelimit. Both middlewares work but the API specific one doesnt overwrite the global one. (Always both are applied) How can I change that?
The code below is part of the current solution. It’s a work-around. At the beginning of the post I mentioned using two types of middlewares. (global/api) Here we use only the global middleware.
Basically using if/else statements checking for the path in the request. If it is one of the endpoints we’d want other limits to be applied it returns only the specific limit settings for that path. It would continue/repeat for all paths and at the end without a condition returning the global rate limit settings.
It’s fine and it works but we’d still like to find another way.
/**
* `rate-limit` middleware (settings based on koa 2 documentation)
*/
module.exports =
(config, { strapi }) =>
async (ctx, next) => {
strapi.log.info('In rate-limit middleware.');
const ratelimit = require('koa2-ratelimit').RateLimit;
const message = [
{
messages: [
{
id: 'Auth.form.error.ratelimit',
message: 'Too many attempts, please try again in a minute.',
},
],
},
];
// rate-limit settings for restaurant endpoint
if (ctx.request.url.toLowerCase().includes('/restaurant/myrestaurant/')) {
return ratelimit.middleware({
interval: { min: 1 }, // time where requests are being kept in memory (use milliseconds or time type syntax)
delayAfter: 10, // after x requests during interval, following requests are slowed down by timeWait amount
timeWait: { ms: 100 }, // slow down by x miliseconds
max: 30, // starts blocking after x amount of requests
// request limit set per path and username when logged in
// request limit set per path and ip when not logged in
prefixKey: `1m:${
ctx.state && ctx.state.user && ctx.state.user.username
? ctx.request.path + ':' + ctx.state.user.username.toUpperCase()
: ctx.request.path + ':' + ctx.request.ip
}`,
message,
...config,
})(ctx, next);