summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/ApiCallService.ts
diff options
context:
space:
mode:
authorKisaragi <48310258+KisaragiEffective@users.noreply.github.com>2024-06-13 10:56:26 +0900
committerGitHub <noreply@github.com>2024-06-13 10:56:26 +0900
commitdc3629e732e5aefd792452f0b43a7bb7fdaf103e (patch)
treec10692a00f80c034498d76967d480be9f9104f95 /packages/backend/src/server/api/ApiCallService.ts
parentnode 22 support (diff)
downloadsharkey-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.ts27
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.');
+ }
});
}
}