import { NextResponse } from "next/server"; export const runtime = "nodejs"; export async function POST(req: Request) { try { // 1) env check const uploadUrl = process.env.CDN_UPLOAD_URL; const token = process.env.CDN_SERVICE_TOKEN; if (!uploadUrl) { return NextResponse.json( { error: "Missing env: CDN_UPLOAD_URL" }, { status: 500 }, ); } if (!token) { return NextResponse.json( { error: "Missing env: CDN_SERVICE_TOKEN" }, { status: 500 }, ); } // 2) read multipart const incoming = await req.formData(); const file = incoming.get("file"); if (!file) { return NextResponse.json( { error: "file is required (field name must be 'file')" }, { status: 400 }, ); } // In Next route handlers, this should be a Web File if (!(file instanceof File)) { return NextResponse.json( { error: "Invalid file type", receivedType: Object.prototype.toString.call(file), }, { status: 400 }, ); } // 3) forward to CDN const fd = new FormData(); fd.append("file", file, file.name); const cdnRes = await fetch(uploadUrl, { method: "POST", headers: { Authorization: `Bearer ${token}`, }, body: fd, }); const contentType = cdnRes.headers.get("content-type") || ""; const isJson = contentType.includes("application/json"); const payload = isJson ? await cdnRes.json() : await cdnRes.text(); if (!cdnRes.ok) { return NextResponse.json( { error: "CDN upload failed", status: cdnRes.status, payload, }, { status: cdnRes.status }, ); } return NextResponse.json(payload); } catch (e: unknown) { // 4) robust error serialization (no toString on undefined) let details = "unknown error"; if (e instanceof Error) details = e.message; else if (typeof e === "string") details = e; else { try { details = JSON.stringify(e); } catch { details = "non-serializable error"; } } return NextResponse.json( { error: "Unexpected error", details }, { status: 500 }, ); } }