import { NextRequest, NextResponse } from 'next/server' const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000' async function handler(request: NextRequest): Promise { const url = new URL(request.url) const targetPath = url.pathname.replace('/api/proxy', '') const targetUrl = `${API_BASE}${targetPath}${url.search}` const headers = new Headers(request.headers) // Remove Next.js internal headers that would confuse the upstream server. // Keep (or relay) x-forwarded-for so the backend's rate limiter can // identify individual clients — without it, all users share the Next.js // server IP and a single rate-limit bucket. headers.delete('host') headers.delete('x-forwarded-host') headers.delete('x-forwarded-proto') // Relay real client IP. Prefer the header Vercel/CDN already set; fall // back to x-real-ip; ultimately unknown if neither is present (e.g. local // dev through a raw Node server). const clientIp = request.headers.get('x-forwarded-for') ?? request.headers.get('x-real-ip') ?? 'unknown' headers.set('x-forwarded-for', clientIp) const body = request.method !== 'GET' && request.method !== 'HEAD' ? await request.arrayBuffer() : undefined try { const upstream = await fetch(targetUrl, { method: request.method, headers, body, }) const responseHeaders = new Headers(upstream.headers) responseHeaders.delete('transfer-encoding') const responseBody = await upstream.arrayBuffer() return new NextResponse(responseBody, { status: upstream.status, statusText: upstream.statusText, headers: responseHeaders, }) } catch (err) { return NextResponse.json( { error: 'Upstream request failed', detail: String(err) }, { status: 502 }, ) } } export const GET = handler export const POST = handler export const PUT = handler export const PATCH = handler export const DELETE = handler export const HEAD = handler export const OPTIONS = handler