Skip to content

Commit

Permalink
Revert "feat(backend): report Retry-After if client hit rate limit (m…
Browse files Browse the repository at this point in the history
…isskey-dev#13949)"

This reverts commit dc3629e.
  • Loading branch information
kanarikanaru committed Jun 13, 2024
1 parent a24e902 commit 3aa7e78
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 40 deletions.
27 changes: 6 additions & 21 deletions packages/backend/src/server/api/ApiCallService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,6 @@ 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;
}
Expand Down Expand Up @@ -318,17 +308,12 @@ 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 => {
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.');
}
throw new ApiError({
message: 'Rate limit exceeded. Please try again later.',
code: 'RATE_LIMIT_EXCEEDED',
id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef',
httpStatusCode: 429,
});
});
}
}
Expand Down
36 changes: 17 additions & 19 deletions packages/backend/src/server/api/RateLimiterService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ export class RateLimiterService {

@bindThis
public limit(limitation: IEndpointMeta['limit'] & { key: NonNullable<string> }, actor: string, factor = 1) {
{
if (this.disabled) {
return Promise.resolve();
}
return new Promise<void>((ok, reject) => {
if (this.disabled) ok();

// Short-term limit
const min = new Promise<void>((ok, reject) => {
const min = (): void => {
const minIntervalLimiter = new Limiter({
id: `${actor}:${limitation.key}:min`,
duration: limitation.minInterval! * factor,
Expand All @@ -48,25 +46,25 @@ export class RateLimiterService {

minIntervalLimiter.get((err, info) => {
if (err) {
return reject({ code: 'ERR', info });
return reject('ERR');
}

this.logger.debug(`${actor} ${limitation.key} min remaining: ${info.remaining}`);

if (info.remaining === 0) {
return reject({ code: 'BRIEF_REQUEST_INTERVAL', info });
reject('BRIEF_REQUEST_INTERVAL');
} else {
if (hasLongTermLimit) {
return max;
max();
} else {
return ok();
ok();
}
}
});
});
};

// Long term limit
const max = new Promise<void>((ok, reject) => {
const max = (): void => {
const limiter = new Limiter({
id: `${actor}:${limitation.key}`,
duration: limitation.duration! * factor,
Expand All @@ -76,18 +74,18 @@ export class RateLimiterService {

limiter.get((err, info) => {
if (err) {
return reject({ code: 'ERR', info });
return reject('ERR');
}

this.logger.debug(`${actor} ${limitation.key} max remaining: ${info.remaining}`);

if (info.remaining === 0) {
return reject({ code: 'RATE_LIMIT_EXCEEDED', info });
reject('RATE_LIMIT_EXCEEDED');
} else {
return ok();
ok();
}
});
});
};

const hasShortTermLimit = typeof limitation.minInterval === 'number';

Expand All @@ -96,12 +94,12 @@ export class RateLimiterService {
typeof limitation.max === 'number';

if (hasShortTermLimit) {
return min;
min();
} else if (hasLongTermLimit) {
return max;
max();
} else {
return Promise.resolve();
ok();
}
}
});
}
}

0 comments on commit 3aa7e78

Please sign in to comment.