add dist
This commit is contained in:
Vendored
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Per-IP sliding window, in memory.
|
||||
*
|
||||
* Deliberately simple: no Redis, no dependency. The trade-off is that the
|
||||
* counter lives in one process — with several instances behind a load balancer
|
||||
* each keeps its own, so the effective limit is per-instance, not global. For a
|
||||
* contact form that's fine (it raises the cost of flooding without pretending
|
||||
* to be airtight); a high-security form should put a real limiter in front.
|
||||
*
|
||||
* State is module-level, so it survives between requests but resets on redeploy
|
||||
* — acceptable for abuse throttling.
|
||||
*/ const buckets = new Map();
|
||||
/** Sweep expired buckets occasionally so the map doesn't grow unbounded. */ let lastSweep = Date.now();
|
||||
const SWEEP_INTERVAL = 60_000;
|
||||
function sweep(now) {
|
||||
if (now - lastSweep < SWEEP_INTERVAL) {
|
||||
return;
|
||||
}
|
||||
lastSweep = now;
|
||||
for (const [key, bucket] of buckets){
|
||||
if (bucket.resetAt <= now) {
|
||||
buckets.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns true when the request is within the limit, false when it should be
|
||||
* rejected. A missing key (no IP) is allowed through — better to accept a
|
||||
* submission than to block everyone behind a proxy that strips the header.
|
||||
*/ export function checkRateLimit({ key, max = 5, windowMs = 60_000 }) {
|
||||
if (!key) {
|
||||
return true;
|
||||
}
|
||||
const now = Date.now();
|
||||
sweep(now);
|
||||
const bucket = buckets.get(key);
|
||||
if (!bucket || bucket.resetAt <= now) {
|
||||
buckets.set(key, {
|
||||
count: 1,
|
||||
resetAt: now + windowMs
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (bucket.count >= max) {
|
||||
return false;
|
||||
}
|
||||
bucket.count += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=rateLimit.js.map
|
||||
Reference in New Issue
Block a user