Hemmelig.app/server/plugins/rate-limit.js
bjarneo 0c86efd56c
refactor: use fastify vite for the dev server (#284)
* refactor: use fastify vite for the server

by doing this we do not need to have local hacks for the routes. No local proxy needed. Everything just works.

* fix: update the dockerfile build path

* fix: update package.json

* fix: fonts path
2024-03-11 13:43:20 +01:00

55 lines
1.6 KiB
JavaScript

import fp from 'fastify-plugin';
import getClientIp from '../helpers/client-ip.js';
const store = new Map();
const defaultOptions = {
prefix: '/',
max: 1000, // x requests
timeWindow: 60 * 1000, // 1 minute
};
// Consider to extract this functionality to a separate plugin,
// and publish it on NPM
// Refactor the code into a class
// and make a redis adapter for it
export default fp((fastify, options = {}, done) => {
const settings = { ...defaultOptions, ...options };
fastify.decorate('rateLimit', async (req, res) => {
if (!req.url.startsWith(settings.prefix)) {
return;
}
const ip = getClientIp(req.headers);
const key = `${req.method}${req.url}${ip}`;
const currentTime = Date.now();
if (!store.has(key) || currentTime > store.get(key)?.reset) {
store.set(key, {
count: 0,
reset: currentTime + settings.timeWindow,
});
}
const current = store.get(key);
current.count += 1;
const resetTime = Math.floor((current.reset - currentTime) / 1000);
if (current.count > settings.max && currentTime <= current.reset) {
res.header('X-RateLimit-Reset', resetTime);
return res.code(429).send({ message: 'Too many requests, please try again later.' });
}
res.header('X-RateLimit-Limit', settings.max);
res.header('X-RateLimit-Remaining', settings.max - current.count);
res.header('X-RateLimit-Reset', resetTime);
});
fastify.addHook('onRequest', fastify.rateLimit);
done();
});