Files
hounam-submit-form-frontend/app/api/cdn/upload/route.ts
2026-06-02 17:08:52 +03:30

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 },
);
}
}