Skip to content

Instantly share code, notes, and snippets.

@slavaGanzin
Created February 5, 2024 10:39
Show Gist options
  • Save slavaGanzin/e5ef94868588001445558e38d88a2143 to your computer and use it in GitHub Desktop.
Save slavaGanzin/e5ef94868588001445558e38d88a2143 to your computer and use it in GitHub Desktop.
basic rate limiter
const requestLimit = new Map();
const requestLimitWindow = [];
const CLEANUP_INTERVAL = 100;
const TEST_RATE = 5;
const IP_LIMIT = 10;
const getLimitKey = () => {
const now = new Date();
return `${now.getHours()}:${now.getMinutes()}:${now.getSeconds().toString().padStart(2, '0')}`;
};
setInterval(() => {
const limitKey = getLimitKey()
for (const i in requestLimitWindow) {
const limit = requestLimitWindow[i]
if (limit['key'] > limitKey) {
return
}
for (const [ip, numberOfRequests] of Object.entries(limit['ips'])) {
requestLimit.set(ip, requestLimit.get(ip) - numberOfRequests);
}
delete requestLimitWindow[i]
}
}, CLEANUP_INTERVAL)
const rateLimiter = (req, res, next) => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
if (requestLimit.get(ip) > IP_LIMIT) return res.send(429);
requestLimit.set(ip, (requestLimit.get(ip) || 0) + 1);
const limitKey = getLimitKey()
let currentWindow = requestLimitWindow[requestLimitWindow.length-1]
if (!currentWindow || currentWindow['key'] != limitKey) {
currentWindow = {
key: limitKey,
ips: {[ip]: 0}
}
requestLimitWindow.push(currentWindow)
}
currentWindow.ips[ip] += 1
next()
}
// app.use(rateLimiter)
// FOR TEST
setInterval(() => {
rateLimiter({headers: {}, connection: {remoteAddress: '127.0.0.1'}}, {send: console.log}, m => console.log('next'+(m||'')))
}, TEST_RATE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment