@thi.ng/server
Version:
Minimal HTTP server with declarative routing, static file serving and freely extensible via pre/post interceptors
33 lines (32 loc) • 843 B
JavaScript
import { isNumber } from "@thi.ng/checks";
import { LeakyBucketMap } from "@thi.ng/leaky-bucket";
const rateLimiter = (opts) => new RateLimiter(opts);
class RateLimiter {
buckets;
capacity;
clientID;
constructor({
id,
maxBuckets,
bucketCapacity,
leakInterval
}) {
this.clientID = id ?? ((ctx) => ctx.req.socket.remoteAddress);
this.capacity = isNumber(bucketCapacity) ? () => bucketCapacity : bucketCapacity;
this.buckets = new LeakyBucketMap({ leakInterval, maxBuckets });
}
pre(ctx) {
const id = this.clientID(ctx);
if (!id) return true;
const cap = !this.buckets.has(id) ? this.capacity(ctx, id) : void 0;
if (!this.buckets.update(id, cap)) {
ctx.res.rateLimit({}, `Try again later.`);
return false;
}
return true;
}
}
export {
RateLimiter,
rateLimiter
};