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);
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) {
let reset = offender.expires_at.getTime();
let resetAfterMs = reset - Date.now();
@ -96,6 +103,12 @@ export default function rateLimit(opts: {
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) {
const global = bucket_id === "global";
// 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}`, {
resetAfterMs,
});
if (global) res.set("X-RateLimit-Global", "true");
return (
res
.status(429)
.set("X-RateLimit-Limit", `${max_hits}`)
.set("X-RateLimit-Remaining", "0")
.set("X-RateLimit-Reset", `${reset}`)
.set("X-RateLimit-Reset-After", `${resetAfterSec}`)
.set("X-RateLimit-Global", `${global}`)
.set("Retry-After", `${Math.ceil(resetAfterSec)}`)
.set("X-RateLimit-Bucket", `${bucket_id}`)
.set(
"Retry-After",
`${Math.max(0, Math.ceil(resetAfterSec))}`,
)
// TODO: error rate limit message translation
.send({
message: "You are being rate limited.",