feat: better rate limit errors

This commit is contained in:
Daniel Hougaard
2024-10-19 06:35:49 +04:00
parent be00d13a46
commit 77a88f1575
3 changed files with 22 additions and 1 deletions
+7
View File
@@ -71,6 +71,13 @@ export class BadRequestError extends Error {
} }
} }
export class RateLimitError extends Error {
constructor({ message }: { message?: string }) {
super(message || "Rate limit exceeded");
this.name = "RateLimitExceeded";
}
}
export class NotFoundError extends Error { export class NotFoundError extends Error {
name: string; name: string;
+6
View File
@@ -2,6 +2,7 @@ import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-lim
import { Redis } from "ioredis"; import { Redis } from "ioredis";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { RateLimitError } from "@app/lib/errors";
export const globalRateLimiterCfg = (): RateLimitPluginOptions => { export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
const appCfg = getConfig(); const appCfg = getConfig();
@@ -10,6 +11,11 @@ export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
: null; : null;
return { return {
errorResponseBuilder: (_, context) => {
throw new RateLimitError({
message: `Rate limit exceeded. Please try again in ${context.after}`
});
},
timeWindow: 60 * 1000, timeWindow: 60 * 1000,
max: 600, max: 600,
redis, redis,
+9 -1
View File
@@ -10,6 +10,7 @@ import {
GatewayTimeoutError, GatewayTimeoutError,
InternalServerError, InternalServerError,
NotFoundError, NotFoundError,
RateLimitError,
ScimRequestError, ScimRequestError,
UnauthorizedError UnauthorizedError
} from "@app/lib/errors"; } from "@app/lib/errors";
@@ -27,7 +28,8 @@ enum HttpStatusCodes {
Forbidden = 403, Forbidden = 403,
// eslint-disable-next-line @typescript-eslint/no-shadow // eslint-disable-next-line @typescript-eslint/no-shadow
InternalServerError = 500, InternalServerError = 500,
GatewayTimeout = 504 GatewayTimeout = 504,
RateLimitExceeded = 429
} }
export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider) => { export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider) => {
@@ -69,6 +71,12 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
message: error.message, message: error.message,
error: error.name error: error.name
}); });
} else if (error instanceof RateLimitError) {
void res.status(HttpStatusCodes.RateLimitExceeded).send({
statusCode: HttpStatusCodes.RateLimitExceeded,
message: error.message,
error: error.name
});
} else if (error instanceof ScimRequestError) { } else if (error instanceof ScimRequestError) {
void res.status(error.status).send({ void res.status(error.status).send({
schemas: error.schemas, schemas: error.schemas,