diff options
| author | Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> | 2024-06-13 10:56:26 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-13 10:56:26 +0900 |
| commit | dc3629e732e5aefd792452f0b43a7bb7fdaf103e (patch) | |
| tree | c10692a00f80c034498d76967d480be9f9104f95 /packages/backend/src/server/api/ApiCallService.ts | |
| parent | node 22 support (diff) | |
| download | sharkey-dc3629e732e5aefd792452f0b43a7bb7fdaf103e.tar.gz sharkey-dc3629e732e5aefd792452f0b43a7bb7fdaf103e.tar.bz2 sharkey-dc3629e732e5aefd792452f0b43a7bb7fdaf103e.zip | |
feat(backend): report `Retry-After` if client hit rate limit (#13949)
* feat(backend): report `Retry-After` if client hit rate limit
* refactor(backend): fix lint error
Diffstat (limited to 'packages/backend/src/server/api/ApiCallService.ts')
| -rw-r--r-- | packages/backend/src/server/api/ApiCallService.ts | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 166f9c8675..47f64f6609 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -73,6 +73,16 @@ export class ApiCallService implements OnApplicationShutdown { reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="insufficient_scope", error_description="${err.message}"`); } statusCode = statusCode ?? 403; + } else if (err.code === 'RATE_LIMIT_EXCEEDED') { + const info: unknown = err.info; + const unixEpochInSeconds = Date.now(); + if (typeof(info) === 'object' && info && 'resetMs' in info && typeof(info.resetMs) === 'number') { + const cooldownInSeconds = Math.ceil((info.resetMs - unixEpochInSeconds) / 1000); + // もしかするとマイナスになる可能性がなくはないのでマイナスだったら0にしておく + reply.header('Retry-After', Math.max(cooldownInSeconds, 0).toString(10)); + } else { + this.logger.warn(`rate limit information has unexpected type ${typeof(err.info?.reset)}`); + } } else if (!statusCode) { statusCode = 500; } @@ -308,12 +318,17 @@ export class ApiCallService implements OnApplicationShutdown { if (factor > 0) { // Rate limit await this.rateLimiterService.limit(limit as IEndpointMeta['limit'] & { key: NonNullable<string> }, limitActor, factor).catch(err => { - throw new ApiError({ - message: 'Rate limit exceeded. Please try again later.', - code: 'RATE_LIMIT_EXCEEDED', - id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef', - httpStatusCode: 429, - }); + if ('info' in err) { + // errはLimiter.LimiterInfoであることが期待される + throw new ApiError({ + message: 'Rate limit exceeded. Please try again later.', + code: 'RATE_LIMIT_EXCEEDED', + id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef', + httpStatusCode: 429, + }, err.info); + } else { + throw new TypeError('information must be a rate-limiter information.'); + } }); } } |