41 lines
1,015 B
TypeScript
41 lines
1,015 B
TypeScript
// Simple in-memory rate limiter. No external dependencies.
|
|
// Tracks requests per IP with a sliding window.
|
|
|
|
interface RateLimitEntry {
|
|
count: number
|
|
resetAt: number
|
|
}
|
|
|
|
const store = new Map<string, RateLimitEntry>()
|
|
|
|
// Clean up expired entries periodically
|
|
setInterval(() => {
|
|
const now = Date.now()
|
|
for (const [key, entry] of store) {
|
|
if (entry.resetAt < now) store.delete(key)
|
|
}
|
|
}, 60_000)
|
|
|
|
/**
|
|
* Check if a request should be rate-limited.
|
|
* @param key - Unique identifier (e.g. IP address)
|
|
* @param limit - Max requests per window
|
|
* @param windowMs - Time window in milliseconds
|
|
* @returns true if the request is allowed, false if rate-limited
|
|
*/
|
|
export function rateLimit(key: string, limit: number, windowMs: number): boolean {
|
|
const now = Date.now()
|
|
const entry = store.get(key)
|
|
|
|
if (!entry || entry.resetAt < now) {
|
|
store.set(key, { count: 1, resetAt: now + windowMs })
|
|
return true
|
|
}
|
|
|
|
if (entry.count >= limit) {
|
|
return false
|
|
}
|
|
|
|
entry.count++
|
|
return true
|
|
}
|