chore: improve api-v2 rate limiting (#16746)

This commit is contained in:
Morgan
2024-09-20 15:15:48 +00:00
committed by GitHub
parent 97f213f260
commit 74bed31edc
2 changed files with 49 additions and 2 deletions
+4 -2
View File
@@ -1,4 +1,5 @@
import appConfig from "@/config/app";
import { CustomThrottlerGuard } from "@/lib/throttler-guard";
import { AppLoggerMiddleware } from "@/middleware/app.logger.middleware";
import { RewriterMiddleware } from "@/middleware/app.rewrites.middleware";
import { JsonBodyMiddleware } from "@/middleware/body/json.body.middleware";
@@ -15,7 +16,7 @@ import { BullModule } from "@nestjs/bull";
import { MiddlewareConsumer, Module, NestModule, RequestMethod } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core";
import { seconds, ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler";
import { seconds, ThrottlerModule } from "@nestjs/throttler";
import { ThrottlerStorageRedisService } from "nestjs-throttler-storage-redis";
import { AppController } from "./app.controller";
@@ -32,6 +33,7 @@ import { AppController } from "./app.controller";
BullModule.forRoot({
redis: `${process.env.REDIS_URL}${process.env.NODE_ENV === "production" ? "?tls=true" : ""}`,
}),
// Rate limiting here is handled by the CustomThrottlerGuard
ThrottlerModule.forRootAsync({
imports: [RedisModule],
inject: [RedisService],
@@ -59,7 +61,7 @@ import { AppController } from "./app.controller";
},
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
useClass: CustomThrottlerGuard,
},
],
})
+45
View File
@@ -0,0 +1,45 @@
import { isApiKey } from "@/lib/api-key";
import { Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Reflector } from "@nestjs/core";
import { ThrottlerGuard, ThrottlerModuleOptions, ThrottlerStorage } from "@nestjs/throttler";
import { Request } from "express";
import { X_CAL_CLIENT_ID } from "@calcom/platform-constants";
@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
private logger = new Logger("CustomThrottlerGuard");
constructor(
options: ThrottlerModuleOptions,
storageService: ThrottlerStorage,
reflector: Reflector,
private readonly config: ConfigService
) {
super(options, storageService, reflector);
}
protected async getTracker(request: Request): Promise<string> {
const authorizationHeader = request.get("Authorization")?.replace("Bearer ", "");
if (authorizationHeader) {
return isApiKey(authorizationHeader, this.config.get<string>("api.apiKeyPrefix") ?? "cal_")
? `api_key_${authorizationHeader}`
: `access_token_${authorizationHeader}`;
}
const oauthClientId = request.get(X_CAL_CLIENT_ID);
if (oauthClientId) {
return oauthClientId;
}
if (request.ip) {
return request.ip;
}
this.logger.log(`no tracker found: ${request.url}`);
return "unknown";
}
}