Send ratelimit headers regardless of if request was blocked (close #1022, close #888)

This commit is contained in:
Madeline 2023-08-10 19:40:41 +10:00
parent d811b20aab
commit 08ff93dab0
No known key found for this signature in database
GPG Key ID: 1958E017C36F2E47

View File

@ -83,6 +83,13 @@ export default function rateLimit(opts: {
const offender = Cache.get(executor_id + bucket_id); const offender = Cache.get(executor_id + bucket_id);
res.set("X-RateLimit-Limit", `${max_hits}`)
.set("X-RateLimit-Remaining", `${max_hits - (offender?.hits || 0)}`)
.set("X-RateLimit-Bucket", `${bucket_id}`)
// assuming we aren't blocked, a new window will start after this request
.set("X-RateLimit-Reset", `${Date.now() + opts.window}`)
.set("X-RateLimit-Reset-After", `${opts.window}`);
if (offender) { if (offender) {
let reset = offender.expires_at.getTime(); let reset = offender.expires_at.getTime();
let resetAfterMs = reset - Date.now(); let resetAfterMs = reset - Date.now();
@ -96,6 +103,12 @@ export default function rateLimit(opts: {
Cache.delete(executor_id + bucket_id); Cache.delete(executor_id + bucket_id);
} }
res.set("X-RateLimit-Reset", `${reset}`);
res.set(
"X-RateLimit-Reset-After",
`${Math.max(0, Math.ceil(resetAfterSec))}`,
);
if (offender.blocked) { if (offender.blocked) {
const global = bucket_id === "global"; const global = bucket_id === "global";
// each block violation pushes the expiry one full window further // each block violation pushes the expiry one full window further
@ -109,16 +122,17 @@ export default function rateLimit(opts: {
console.log(`blocked bucket: ${bucket_id} ${executor_id}`, { console.log(`blocked bucket: ${bucket_id} ${executor_id}`, {
resetAfterMs, resetAfterMs,
}); });
if (global) res.set("X-RateLimit-Global", "true");
return ( return (
res res
.status(429) .status(429)
.set("X-RateLimit-Limit", `${max_hits}`)
.set("X-RateLimit-Remaining", "0") .set("X-RateLimit-Remaining", "0")
.set("X-RateLimit-Reset", `${reset}`) .set(
.set("X-RateLimit-Reset-After", `${resetAfterSec}`) "Retry-After",
.set("X-RateLimit-Global", `${global}`) `${Math.max(0, Math.ceil(resetAfterSec))}`,
.set("Retry-After", `${Math.ceil(resetAfterSec)}`) )
.set("X-RateLimit-Bucket", `${bucket_id}`)
// TODO: error rate limit message translation // TODO: error rate limit message translation
.send({ .send({
message: "You are being rate limited.", message: "You are being rate limited.",