refactor: throttler rate limits for oauth client & access token (#16962)
Co-authored-by: Morgan Vernay <morgan@cal.com>
This commit is contained in:
co-authored by
Morgan Vernay
parent
5ed36a7fe1
commit
c4cdba1015
@@ -21,6 +21,9 @@ export type Environment = {
|
||||
API_KEY_PREFIX: string;
|
||||
DOCS_URL: string;
|
||||
RATE_LIMIT_DEFAULT_TTL_MS: number;
|
||||
RATE_LIMIT_DEFAULT_LIMIT_API_KEY: number;
|
||||
RATE_LIMIT_DEFAULT_LIMIT_OAUTH_CLIENT: number;
|
||||
RATE_LIMIT_DEFAULT_LIMIT_ACCESS_TOKEN: number;
|
||||
RATE_LIMIT_DEFAULT_LIMIT: number;
|
||||
RATE_LIMIT_DEFAULT_BLOCK_DURATION_MS: number;
|
||||
};
|
||||
|
||||
@@ -22,18 +22,23 @@ const rateLimitSchema = z.object({
|
||||
ttl: z.number(),
|
||||
blockDuration: z.number(),
|
||||
});
|
||||
|
||||
type RateLimitType = z.infer<typeof rateLimitSchema>;
|
||||
|
||||
const rateLimitsSchema = z.array(rateLimitSchema);
|
||||
|
||||
const sixtySecondsMs = 60 * 1000;
|
||||
|
||||
@Injectable()
|
||||
export class CustomThrottlerGuard extends ThrottlerGuard {
|
||||
private logger = new Logger("CustomThrottlerGuard");
|
||||
|
||||
private defaultTttl = Number(getEnv("RATE_LIMIT_DEFAULT_TTL_MS", 60 * 1000));
|
||||
private defaultTttl = Number(getEnv("RATE_LIMIT_DEFAULT_TTL_MS", sixtySecondsMs));
|
||||
|
||||
private defaultLimitApiKey = Number(getEnv("RATE_LIMIT_DEFAULT_LIMIT_API_KEY", 120));
|
||||
private defaultLimitOAuthClient = Number(getEnv("RATE_LIMIT_DEFAULT_LIMIT_OAUTH_CLIENT", 500));
|
||||
private defaultLimitAccessToken = Number(getEnv("RATE_LIMIT_DEFAULT_LIMIT_ACCESS_TOKEN", 500));
|
||||
private defaultLimit = Number(getEnv("RATE_LIMIT_DEFAULT_LIMIT", 120));
|
||||
private defaultBlockDuration = Number(getEnv("RATE_LIMIT_DEFAULT_BLOCK_DURATION_MS", 60 * 1000));
|
||||
|
||||
private defaultBlockDuration = Number(getEnv("RATE_LIMIT_DEFAULT_BLOCK_DURATION_MS", sixtySecondsMs));
|
||||
|
||||
constructor(
|
||||
options: ThrottlerModuleOptions,
|
||||
@@ -83,7 +88,7 @@ export class CustomThrottlerGuard extends ThrottlerGuard {
|
||||
}
|
||||
|
||||
private async handleNonApiKeyRequest(tracker: string, response: Response): Promise<boolean> {
|
||||
const rateLimit = this.getDefaultRateLimit();
|
||||
const rateLimit = this.getDefaultRateLimit(tracker);
|
||||
this.logger.log(`Tracker "${tracker}" uses default rate limits because it is not tracking api key:
|
||||
${JSON.stringify(rateLimit, null, 2)}
|
||||
`);
|
||||
@@ -96,17 +101,25 @@ export class CustomThrottlerGuard extends ThrottlerGuard {
|
||||
return true;
|
||||
}
|
||||
|
||||
private getDefaultRateLimit() {
|
||||
private getDefaultRateLimit(tracker: string) {
|
||||
return {
|
||||
name: "default",
|
||||
limit: this.getDefaultLimit(),
|
||||
limit: this.getDefaultLimit(tracker),
|
||||
ttl: this.getDefaultTtl(),
|
||||
blockDuration: this.getDefaultBlockDuration(),
|
||||
};
|
||||
}
|
||||
|
||||
getDefaultLimit() {
|
||||
return this.defaultLimit;
|
||||
getDefaultLimit(tracker: string) {
|
||||
if (tracker.startsWith("api_key_")) {
|
||||
return this.defaultLimitApiKey;
|
||||
} else if (tracker.startsWith("oauth_client_")) {
|
||||
return this.defaultLimitOAuthClient;
|
||||
} else if (tracker.startsWith("access_token_")) {
|
||||
return this.defaultLimitAccessToken;
|
||||
} else {
|
||||
return this.defaultLimit;
|
||||
}
|
||||
}
|
||||
|
||||
getDefaultTtl() {
|
||||
@@ -150,7 +163,7 @@ export class CustomThrottlerGuard extends ThrottlerGuard {
|
||||
}
|
||||
|
||||
if (!rateLimits || rateLimits.length === 0) {
|
||||
rateLimits = [this.getDefaultRateLimit()];
|
||||
rateLimits = [this.getDefaultRateLimit(tracker)];
|
||||
this.logger.log(`Tracker "${tracker}" rate limits not found in database. Using default rate limits:
|
||||
${JSON.stringify(rateLimits, null, 2)}`);
|
||||
}
|
||||
|
||||
+441
-1845
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user