Harden authentication and writable endpoints
This commit is contained in:
parent
c034824338
commit
0a7ee5ff35
33 changed files with 308 additions and 284 deletions
34
app/lib/rate-limit.ts
Normal file
34
app/lib/rate-limit.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
type Bucket = { count: number; resetAt: number };
|
||||
|
||||
const buckets = new Map<string, Bucket>();
|
||||
const MAX_BUCKETS = 10_000;
|
||||
|
||||
export function requestIp(req: Request): string {
|
||||
// The deployment binds Next.js to localhost behind a reverse proxy. The
|
||||
// proxy must replace client-supplied forwarding headers for this to be safe.
|
||||
return (
|
||||
req.headers.get("x-real-ip") ||
|
||||
req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ||
|
||||
"unknown"
|
||||
);
|
||||
}
|
||||
|
||||
export function rateLimit(key: string, max: number, windowMs: number): boolean {
|
||||
const now = Date.now();
|
||||
const current = buckets.get(key);
|
||||
|
||||
if (!current || current.resetAt <= now) {
|
||||
if (buckets.size >= MAX_BUCKETS) {
|
||||
for (const [bucketKey, bucket] of buckets) {
|
||||
if (bucket.resetAt <= now) buckets.delete(bucketKey);
|
||||
}
|
||||
if (buckets.size >= MAX_BUCKETS) buckets.delete(buckets.keys().next().value as string);
|
||||
}
|
||||
buckets.set(key, { count: 1, resetAt: now + windowMs });
|
||||
return true;
|
||||
}
|
||||
|
||||
if (current.count >= max) return false;
|
||||
current.count += 1;
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue