import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; const RATE_LIMIT_WINDOW = 60 * 1000; // 1 minute const MAX_REQUESTS = 100; // 100 requests per window const CLEANUP_THRESHOLD = 500; const ipMap = new Map(); export function middleware(request: NextRequest) { const forwarded = request.headers.get('x-forwarded-for'); const ip = forwarded ? forwarded.split(',')[0].trim() : 'unknown'; const now = Date.now(); console.log(`[${new Date().toISOString()}] Request to ${request.nextUrl.pathname} from ${ip}`); const record = ipMap.get(ip); if (!record || now > record.expires) { ipMap.set(ip, { count: 1, expires: now + RATE_LIMIT_WINDOW }); } else { record.count++; if (record.count > MAX_REQUESTS) { return new NextResponse('Too Many Requests', { status: 429 }); } } // Cleanup old entries probabilistically (1-in-10 requests) if (ipMap.size > CLEANUP_THRESHOLD && Math.random() < 0.1) { for (const [key, val] of ipMap.entries()) { if (now > val.expires) { ipMap.delete(key); } } } return NextResponse.next(); } export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico)$).*)'], };