mirror of
https://github.com/LukeHagar/pypistats.dev.git
synced 2025-12-06 04:21:09 +00:00
removing rate limit for now
This commit is contained in:
@@ -1,86 +1,6 @@
|
||||
import { closeRedisClient, forceDisconnectRedis, getRedisClient } from '$lib/redis.js';
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
|
||||
// Minimal server hooks without cron
|
||||
if (typeof process !== 'undefined') {
|
||||
// Graceful shutdown
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('🛑 Received SIGTERM, closing connections...');
|
||||
await closeRedisClient();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('🛑 Received SIGINT, closing connections...');
|
||||
await closeRedisClient();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Handle uncaught exceptions
|
||||
process.on('uncaughtException', async (error) => {
|
||||
console.error('🛑 Uncaught Exception:', error);
|
||||
await forceDisconnectRedis();
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', async (reason, promise) => {
|
||||
console.error('🛑 Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
await forceDisconnectRedis();
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
// Sliding window rate limit parameters
|
||||
const WINDOW_SECONDS = 60; // 1 minute
|
||||
const MAX_REQUESTS = 15; // per ip per window
|
||||
|
||||
async function consumeSlidingWindow(key: string, points: number, windowSeconds: number) {
|
||||
const client = getRedisClient();
|
||||
if (!client) return { allowed: true, remaining: MAX_REQUESTS };
|
||||
const now = Date.now();
|
||||
const windowStart = now - windowSeconds * 1000;
|
||||
const listKey = `rl:sw:${key}`;
|
||||
|
||||
// Remove old entries and push current
|
||||
const lua = `
|
||||
local key = KEYS[1]
|
||||
local now = tonumber(ARGV[1])
|
||||
local windowStart = tonumber(ARGV[2])
|
||||
local points = tonumber(ARGV[3])
|
||||
local limit = tonumber(ARGV[4])
|
||||
-- Trim old timestamps
|
||||
redis.call('ZREMRANGEBYSCORE', key, 0, windowStart)
|
||||
-- Add current request timestamps (as single timestamp repeated 'points' times)
|
||||
for i=1,points do
|
||||
redis.call('ZADD', key, now, now .. '-' .. i)
|
||||
end
|
||||
local count = redis.call('ZCARD', key)
|
||||
-- Set expiry just beyond window
|
||||
redis.call('EXPIRE', key, windowStart + (60*60*24) == 0 and 60 or math.floor((now - windowStart)/1000) + 5)
|
||||
return count
|
||||
`;
|
||||
const count = await client.send(lua, [listKey, String(now), String(windowStart), String(points), String(MAX_REQUESTS)]);
|
||||
return { allowed: count <= MAX_REQUESTS, remaining: Math.max(0, MAX_REQUESTS - count) };
|
||||
}
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
// Only apply to API routes
|
||||
if (event.url.pathname.startsWith('/api/')) {
|
||||
// Identify client by IP (or forwarded-for)
|
||||
const ip = (event.getClientAddress?.() || event.request.headers.get('x-forwarded-for') || '').split(',')[0].trim() || 'unknown';
|
||||
const key = `ip:${ip}`;
|
||||
const result = await consumeSlidingWindow(key, 1, WINDOW_SECONDS);
|
||||
if (!result.allowed) {
|
||||
const reset = WINDOW_SECONDS; // approximate
|
||||
return new Response('Too Many Requests', {
|
||||
status: 429,
|
||||
headers: {
|
||||
'Retry-After': String(reset),
|
||||
'RateLimit-Policy': `${MAX_REQUESTS};w=${WINDOW_SECONDS}`,
|
||||
'RateLimit-Remaining': '0'
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return resolve(event);
|
||||
};
|
||||
Reference in New Issue
Block a user