use fraction seconds for rate limit headers
This commit is contained in:
parent
7c002ce56e
commit
2bcac80092
2 changed files with 72 additions and 4 deletions
|
@ -126,14 +126,20 @@ export function hasMinLimit(limit: LegacyRateLimit): limit is LegacyRateLimit &
|
||||||
|
|
||||||
export function sendRateLimitHeaders(reply: FastifyReply, info: LimitInfo): void {
|
export function sendRateLimitHeaders(reply: FastifyReply, info: LimitInfo): void {
|
||||||
// Number of seconds until the limit has fully reset.
|
// Number of seconds until the limit has fully reset.
|
||||||
reply.header('X-RateLimit-Clear', info.fullResetSec.toString());
|
const clear = (info.fullResetMs / 1000).toFixed(3);
|
||||||
|
reply.header('X-RateLimit-Clear', clear);
|
||||||
|
|
||||||
// Number of calls that can be made before being limited.
|
// Number of calls that can be made before being limited.
|
||||||
reply.header('X-RateLimit-Remaining', info.remaining.toString());
|
const remaining = info.remaining.toString();
|
||||||
|
reply.header('X-RateLimit-Remaining', remaining);
|
||||||
|
|
||||||
if (info.blocked) {
|
if (info.blocked) {
|
||||||
// Number of seconds to wait before trying again. Left for backwards compatibility.
|
// Number of seconds to wait before trying again. Left for backwards compatibility.
|
||||||
reply.header('Retry-After', info.resetSec.toString());
|
const retry = info.resetSec.toString();
|
||||||
|
reply.header('Retry-After', retry);
|
||||||
|
|
||||||
// Number of milliseconds to wait before trying again.
|
// Number of milliseconds to wait before trying again.
|
||||||
reply.header('X-RateLimit-Reset', info.resetMs.toString());
|
const reset = (info.resetMs / 1000).toFixed(3);
|
||||||
|
reply.header('X-RateLimit-Reset', reset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
62
packages/backend/test/unit/misc/rate-limit-utils-tests.ts
Normal file
62
packages/backend/test/unit/misc/rate-limit-utils-tests.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { jest } from '@jest/globals';
|
||||||
|
import { Mock } from 'jest-mock';
|
||||||
|
import type { FastifyReply } from 'fastify';
|
||||||
|
import { LimitInfo, sendRateLimitHeaders } from '@/misc/rate-limit-utils.js';
|
||||||
|
|
||||||
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
|
|
||||||
|
describe(sendRateLimitHeaders, () => {
|
||||||
|
let mockHeader: Mock<((name: string, value: unknown) => void)> = null!;
|
||||||
|
let mockReply: FastifyReply = null!;
|
||||||
|
let fakeInfo: LimitInfo = null!;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockHeader = jest.fn<((name: string, value: unknown) => void)>();
|
||||||
|
mockReply = {
|
||||||
|
header: mockHeader,
|
||||||
|
} as unknown as FastifyReply;
|
||||||
|
fakeInfo = {
|
||||||
|
blocked: false,
|
||||||
|
remaining: 1,
|
||||||
|
resetSec: 1,
|
||||||
|
resetMs: 567,
|
||||||
|
fullResetSec: 10,
|
||||||
|
fullResetMs: 9876,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send X-RateLimit-Clear', () => {
|
||||||
|
sendRateLimitHeaders(mockReply, fakeInfo);
|
||||||
|
|
||||||
|
expect(mockHeader).toHaveBeenCalledWith('X-RateLimit-Clear', '9.876');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send X-RateLimit-Remaining', () => {
|
||||||
|
sendRateLimitHeaders(mockReply, fakeInfo);
|
||||||
|
|
||||||
|
expect(mockHeader).toHaveBeenCalledWith('X-RateLimit-Remaining', '1');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when limit is blocked', () => {
|
||||||
|
it('should send X-RateLimit-Reset', () => {
|
||||||
|
fakeInfo.blocked = true;
|
||||||
|
|
||||||
|
sendRateLimitHeaders(mockReply, fakeInfo);
|
||||||
|
|
||||||
|
expect(mockHeader).toHaveBeenCalledWith('X-RateLimit-Reset', '0.567');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send Retry-After', () => {
|
||||||
|
fakeInfo.blocked = true;
|
||||||
|
|
||||||
|
sendRateLimitHeaders(mockReply, fakeInfo);
|
||||||
|
|
||||||
|
expect(mockHeader).toHaveBeenCalledWith('Retry-After', '1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue