94 lines
2.2 KiB
TypeScript
94 lines
2.2 KiB
TypeScript
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 },
|
|
);
|
|
}
|
|
}
|