feature(api): add rate limiter
This commit is contained in:
@@ -209,8 +209,16 @@ const startServer = async () => {
|
||||
fastify.register(importRouter, { prefix: '/import' });
|
||||
fastify.register(trackRouter, { prefix: '/track' });
|
||||
fastify.setErrorHandler((error, request, reply) => {
|
||||
request.log.error('request error', { error });
|
||||
reply.status(500).send('Internal server error');
|
||||
if (error.statusCode === 429) {
|
||||
reply.status(429).send({
|
||||
status: 429,
|
||||
error: 'Too Many Requests',
|
||||
message: 'You have exceeded the rate limit for this endpoint.',
|
||||
});
|
||||
} else {
|
||||
request.log.error('request error', { error });
|
||||
reply.status(500).send('Internal server error');
|
||||
}
|
||||
});
|
||||
fastify.get('/', (_request, reply) => {
|
||||
reply.send({ name: 'openpanel sdk api' });
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import * as controller from '@/controllers/export.controller';
|
||||
import { validateExportRequest } from '@/utils/auth';
|
||||
import { activateRateLimiter } from '@/utils/rate-limiter';
|
||||
import { Prisma } from '@openpanel/db';
|
||||
import type { FastifyPluginCallback, FastifyRequest } from 'fastify';
|
||||
|
||||
import { Prisma } from '@openpanel/db';
|
||||
const exportRouter: FastifyPluginCallback = async (fastify, opts, done) => {
|
||||
await activateRateLimiter({
|
||||
fastify,
|
||||
max: 10,
|
||||
timeWindow: '10 seconds',
|
||||
});
|
||||
|
||||
const eventRouter: FastifyPluginCallback = (fastify, opts, done) => {
|
||||
fastify.addHook('preHandler', async (req: FastifyRequest, reply) => {
|
||||
try {
|
||||
const client = await validateExportRequest(req.headers);
|
||||
@@ -43,4 +49,4 @@ const eventRouter: FastifyPluginCallback = (fastify, opts, done) => {
|
||||
done();
|
||||
};
|
||||
|
||||
export default eventRouter;
|
||||
export default exportRouter;
|
||||
|
||||
34
apps/api/src/utils/rate-limiter.ts
Normal file
34
apps/api/src/utils/rate-limiter.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { getRedisCache } from '@openpanel/redis';
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
|
||||
export async function activateRateLimiter({
|
||||
fastify,
|
||||
max,
|
||||
timeWindow,
|
||||
}: {
|
||||
fastify: FastifyInstance;
|
||||
max: number;
|
||||
timeWindow?: string;
|
||||
}) {
|
||||
await fastify.register(import('@fastify/rate-limit'), {
|
||||
max,
|
||||
timeWindow: timeWindow || '1 minute',
|
||||
errorResponseBuilder: (req, reply) => {
|
||||
return {
|
||||
statusCode: 429,
|
||||
error: 'Too Many Requests',
|
||||
message: 'You have exceeded the rate limit for this endpoint.',
|
||||
};
|
||||
},
|
||||
redis: getRedisCache(),
|
||||
keyGenerator(req) {
|
||||
return (req.headers['openpanel-client-id'] ||
|
||||
req.headers['x-real-ip'] ||
|
||||
req.headers['x-client-ip'] ||
|
||||
req.headers['x-forwarded-for']) as string;
|
||||
},
|
||||
onExceeded: (req, reply) => {
|
||||
req.log.warn('Rate limit exceeded');
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user