52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import { ProvisionError } from "@/lib/certificates";
|
|
import { provisionNode } from "@/lib/provisioning";
|
|
export const runtime = "nodejs";
|
|
export async function POST(request: Request) {
|
|
const headers = { "Cache-Control": "no-store" };
|
|
try {
|
|
// Bound streamed input, including requests without Content-Length.
|
|
const reader = request.body?.getReader();
|
|
if (!reader)
|
|
return Response.json(
|
|
{ error: "缺少请求内容。" },
|
|
{ status: 400, headers },
|
|
);
|
|
const chunks: Uint8Array[] = [];
|
|
let size = 0;
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done) break;
|
|
size += value.byteLength;
|
|
if (size > 4096) {
|
|
await reader.cancel();
|
|
return Response.json({ error: "请求过大。" }, { status: 413, headers });
|
|
}
|
|
chunks.push(value);
|
|
}
|
|
let payload;
|
|
try {
|
|
payload = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
} catch {
|
|
return Response.json({ error: "无效 JSON。" }, { status: 400, headers });
|
|
}
|
|
if (!payload || !["prepare", "complete"].includes(payload.action))
|
|
return Response.json({ error: "无效操作。" }, { status: 400, headers });
|
|
const token =
|
|
request.headers.get("authorization")?.replace(/^Bearer /, "") ?? "";
|
|
return Response.json(
|
|
await provisionNode(token, payload.action, payload.ports),
|
|
{ headers },
|
|
);
|
|
} catch (error) {
|
|
return Response.json(
|
|
{
|
|
error:
|
|
error instanceof ProvisionError
|
|
? error.message
|
|
: "安装请求失败,请联系平台管理员。",
|
|
},
|
|
{ status: error instanceof ProvisionError ? 400 : 500, headers },
|
|
);
|
|
}
|
|
}
|