import { NextRequest, NextResponse } from 'next/server' import { auth } from '@/auth' import { isBlockedFetchHost } from '@/lib/ssrf-guard' export async function GET(req: NextRequest) { const session = await auth() if (!session?.user?.id) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const url = req.nextUrl.searchParams.get('url') if (!url) return NextResponse.json({ error: 'Missing url' }, { status: 400 }) try { const parsed = new URL(url) if (!['http:', 'https:'].includes(parsed.protocol)) { return NextResponse.json({ error: 'Invalid protocol' }, { status: 400 }) } if (isBlockedFetchHost(parsed.hostname)) { return NextResponse.json({ error: 'Host not allowed' }, { status: 403 }) } const controller = new AbortController() const timeout = setTimeout(() => controller.abort(), 5000) const res = await fetch(url, { signal: controller.signal, headers: { 'User-Agent': 'Mozilla/5.0 (compatible; MementoBot/1.0)', 'Accept': 'image/*', 'Referer': parsed.origin, }, }) clearTimeout(timeout) if (!res.ok) return NextResponse.json({ error: 'Fetch failed' }, { status: 502 }) const contentType = res.headers.get('content-type') || 'image/jpeg' if (!contentType.startsWith('image/')) { return NextResponse.json({ error: 'Not an image' }, { status: 400 }) } const buffer = await res.arrayBuffer() return new NextResponse(buffer, { headers: { 'Content-Type': contentType, 'Cache-Control': 'public, s-maxage=604800', }, }) } catch { return NextResponse.json({ error: 'Failed' }, { status: 502 }) } }