diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 17c76b2260..9b053a4b95 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -98,6 +98,8 @@ type Source = { proxyRemoteFiles?: boolean; videoThumbnailGenerator?: string; + bypassRateLimit?: { header: string; value: string }[]; + signToActivityPubGet?: boolean; perChannelMaxNoteCacheCount?: number; @@ -175,6 +177,7 @@ export type Config = { mediaProxy: string; externalMediaProxyEnabled: boolean; videoThumbnailGenerator: string | null; + bypassRateLimit: { header: string; value: string }[] | undefined; redis: RedisOptions & RedisOptionsSource; redisForPubsub: RedisOptions & RedisOptionsSource; redisForSystemQueue: RedisOptions & RedisOptionsSource; @@ -288,6 +291,7 @@ export function loadConfig(): Config { videoThumbnailGenerator: config.videoThumbnailGenerator ? config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator : null, + bypassRateLimit: config.bypassRateLimit, userAgent: `Misskey/${version} (${config.url})`, clientEntry: clientManifest['src/_boot_.ts'], clientManifestExists: clientManifestExists, diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index d8e792051e..cd15721b03 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -18,6 +18,7 @@ import { createTemp } from '@/misc/create-temp.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; +import type { Config } from '@/config.js'; import { ApiError } from './error.js'; import { RateLimiterService } from './RateLimiterService.js'; import { ApiLoggerService } from './ApiLoggerService.js'; @@ -39,6 +40,8 @@ export class ApiCallService implements OnApplicationShutdown { private userIpHistoriesClearIntervalId: NodeJS.Timeout; constructor( + @Inject(DI.config) + private config: Config, @Inject(DI.userIpsRepository) private userIpsRepository: UserIpsRepository, @@ -243,7 +246,8 @@ export class ApiCallService implements OnApplicationShutdown { throw new ApiError(accessDenied); } - if (ep.meta.limit) { + const bypassRateLimit = this.config.bypassRateLimit?.some(({ header, value }) => request.headers[header] === value) ?? false; + if (ep.meta.limit && !bypassRateLimit) { // koa will automatically load the `X-Forwarded-For` header if `proxy: true` is configured in the app. let limitActor: string; if (user) {