initial deployment v1.0
This commit is contained in:
55
src/lib/server/ratelimit.js
Normal file
55
src/lib/server/ratelimit.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
// In-memory store: Map<ip, { count, windowStart }>
|
||||
const publishStore = new Map();
|
||||
const readStore = new Map();
|
||||
|
||||
const PUBLISH_LIMIT = parseInt(env.RATE_LIMIT_PUBLISH ?? '5');
|
||||
const READ_LIMIT = parseInt(env.RATE_LIMIT_READ ?? '100');
|
||||
const PUBLISH_WINDOW_MS = 60 * 60 * 1000; // 1 hour
|
||||
const READ_WINDOW_MS = 60 * 1000; // 1 minute
|
||||
|
||||
function check(store, ip, limit, windowMs) {
|
||||
const now = Date.now();
|
||||
const entry = store.get(ip);
|
||||
|
||||
if (!entry || now - entry.windowStart > windowMs) {
|
||||
store.set(ip, { count: 1, windowStart: now });
|
||||
return { allowed: true, remaining: limit - 1 };
|
||||
}
|
||||
|
||||
if (entry.count >= limit) {
|
||||
const retryAfter = Math.ceil((entry.windowStart + windowMs - now) / 1000);
|
||||
return { allowed: false, remaining: 0, retryAfter };
|
||||
}
|
||||
|
||||
entry.count += 1;
|
||||
return { allowed: true, remaining: limit - entry.count };
|
||||
}
|
||||
|
||||
export function checkPublishRate(ip) {
|
||||
return check(publishStore, ip, PUBLISH_LIMIT, PUBLISH_WINDOW_MS);
|
||||
}
|
||||
|
||||
export function checkReadRate(ip) {
|
||||
return check(readStore, ip, READ_LIMIT, READ_WINDOW_MS);
|
||||
}
|
||||
|
||||
export function getClientIp(request) {
|
||||
return (
|
||||
request.headers.get('x-forwarded-for')?.split(',')[0].trim() ??
|
||||
request.headers.get('x-real-ip') ??
|
||||
'127.0.0.1'
|
||||
);
|
||||
}
|
||||
|
||||
// Cleanup old entries every 10 minutes to prevent memory leak
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [ip, entry] of publishStore) {
|
||||
if (now - entry.windowStart > PUBLISH_WINDOW_MS) publishStore.delete(ip);
|
||||
}
|
||||
for (const [ip, entry] of readStore) {
|
||||
if (now - entry.windowStart > READ_WINDOW_MS) readStore.delete(ip);
|
||||
}
|
||||
}, 10 * 60 * 1000);
|
||||
Reference in New Issue
Block a user