import { NextResponse } from "next/server"; import type { FormBlockProps } from "@/features/editor/state/editorStore"; export async function POST(req: Request) { const formData = await req.formData(); // 기본 필드(name/email/message)는 그대로 읽어둔다. const name = formData.get("name"); const email = formData.get("email"); const message = formData.get("message"); // 에디터에서 넘겨준 폼 설정(JSON) 읽기 const rawConfig = formData.get("__config"); let config: FormBlockProps | null = null; if (typeof rawConfig === "string") { try { config = JSON.parse(rawConfig) as FormBlockProps; } catch { config = null; } } const submitTarget = config?.submitTarget ?? "internal"; const successMessage = config?.successMessage; const errorMessage = config?.errorMessage; // 1) internal: 우리 서버에서 직접 처리하는 기본 모드 if (submitTarget === "internal") { // TODO: 이곳에서 DB 저장이나 이메일 전송 등 실제 처리를 수행한다. console.log("[forms/submit][internal]", { name, email, message }); return NextResponse.json({ ok: true, message: successMessage }); } // 2) webhook: destinationUrl 로 서버에서 POST (Google Sheets 등 포함) if (submitTarget === "webhook") { const destinationUrl = config?.destinationUrl; if (!destinationUrl) { return NextResponse.json( { ok: false, error: "destinationUrl_missing", message: errorMessage }, { status: 400 }, ); } const payloadFormat = config?.payloadFormat ?? "form"; let body: string; const headers: Record = { ...(config?.headers ?? {}), }; if (payloadFormat === "json") { const jsonPayload: Record = {}; formData.forEach((value, key) => { if (key !== "__config") { jsonPayload[key] = String(value); } }); if (config?.extraParams) { Object.entries(config.extraParams).forEach(([k, v]) => { jsonPayload[k] = v; }); } headers["Content-Type"] = "application/json"; body = JSON.stringify(jsonPayload); } else { // 기본 동작: FormData -> x-www-form-urlencoded 로 변환 (많은 webhook/Apps Script가 이 형식을 사용) const payload = new URLSearchParams(); formData.forEach((value, key) => { if (key !== "__config") { payload.append(key, String(value)); } }); if (config?.extraParams) { Object.entries(config.extraParams).forEach(([k, v]) => { payload.append(k, v); }); } headers["Content-Type"] = "application/x-www-form-urlencoded"; body = payload.toString(); } try { const res = await fetch(destinationUrl, { method: config?.method ?? "POST", headers, body, }); if (!res.ok) { console.error("[forms/submit][webhook] remote error", res.status, await res.text().catch(() => "")); return NextResponse.json( { ok: false, error: "webhook_failed", message: errorMessage }, { status: 502 }, ); } } catch (error) { console.error("[forms/submit][webhook] fetch error", error); return NextResponse.json( { ok: false, error: "webhook_exception", message: errorMessage }, { status: 500 }, ); } console.log("[forms/submit][webhook] forwarded", { name, email, message, destinationUrl }); return NextResponse.json({ ok: true, message: successMessage }); } // 그 외 알 수 없는 모드는 internal 과 동일하게 처리 console.warn("[forms/submit] unknown submitTarget, fallback to internal", submitTarget); console.log("[forms/submit][internal]", { name, email, message }); return NextResponse.json({ ok: true, message: successMessage }); }