// Rate-limiter: проверяет X-Client-ID, считает запросы в памяти пода // В реальном проекте — Redis. Здесь: in-memory для демонстрации. const counters = {}; const WINDOW_MS = 60_000; const LIMIT = 100; exports.handler = async (ctx) => { const req = ctx.request; const clientId = (req.headers && req.headers["x-client-id"]) || "anonymous"; const now = Date.now(); if (!counters[clientId]) { counters[clientId] = { count: 0, windowStart: now }; } const c = counters[clientId]; if (now - c.windowStart > WINDOW_MS) { c.count = 0; c.windowStart = now; } c.count++; const allowed = c.count <= LIMIT; const remaining = Math.max(0, LIMIT - c.count); const resetAt = new Date(c.windowStart + WINDOW_MS).toISOString(); if (!allowed) { return { status: 429, body: JSON.stringify({ error: "rate limit exceeded", client_id: clientId, limit: LIMIT, reset_at: resetAt, }), headers: { "Content-Type": "application/json", "X-RateLimit-Limit": String(LIMIT), "X-RateLimit-Remaining": "0", "X-RateLimit-Reset": resetAt, }, }; } return { body: JSON.stringify({ allowed: true, client_id: clientId, requests_in_window: c.count, remaining, limit: LIMIT, reset_at: resetAt, }), headers: { "Content-Type": "application/json", "X-RateLimit-Limit": String(LIMIT), "X-RateLimit-Remaining": String(remaining), }, }; };