import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// web-sandbox 오리진은 와일드카드를 헤더에 직접 넣는 게 아니라,
// 요청 origin을 검사해서 "허용이면 그대로 반사"하는 방식으로 처리해야 함.
function isAllowedOrigin(origin: string | null) {
if (!origin) return false;
if (origin === "https://chatgpt.com") return true;
try {
const u = new URL(origin);
// ChatGPT 위젯 샌드박스 도메인 패턴 허용
if (u.hostname.endsWith(".web-sandbox.oaiusercontent.com")) return true;
} catch {}
return false;
}
// 쿠키/세션 등 credentials 안 쓰는 전제: 일단은 가장 단순하게.
function corsHeaders(req: Request) {
const origin = req.headers.get("origin");
const allowOrigin = isAllowedOrigin(origin) ? origin! : "*";
return {
"Access-Control-Allow-Origin": allowOrigin,
"Vary": "Origin", // 캐시가 Origin별로 섞이지 않게
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Max-Age": "86400",
};
}
export async function OPTIONS(req: Request) {
return new Response(null, { status: 204, headers: corsHeaders(req) });
}
export async function POST(req: Request) {
const base = (process.env.MCP_PUBLIC_URL || "").replace(/\/+$/, "");
if (!base) {
return NextResponse.json(
{ ok: false, message: "Missing MCP_PUBLIC_URL" },
{ status: 500, headers: corsHeaders(req) }
);
}
const toolInput = await req.json().catch(() => null);
if (!toolInput) {
return NextResponse.json(
{ ok: false, message: "Invalid JSON" },
{ status: 400, headers: corsHeaders(req) }
);
}
// (중요) upstream 호출 실패를 잡아서 "failed to fetch" 대신 JSON으로 내려주기
let upstreamRes: Response;
let upstreamJson: any = null;
try {
upstreamRes = await fetch(`${base}/saju/calculate`, {
method: "POST",
headers: { "Content-Type": "application/json" },
cache: "no-store",
body: JSON.stringify(toolInput),
});
upstreamJson = await upstreamRes.json().catch(() => null);
} catch (e: any) {
return NextResponse.json(
{ ok: false, message: `Upstream fetch failed: ${e?.message || String(e)}` },
{ status: 502, headers: corsHeaders(req) }
);
}
return NextResponse.json(
upstreamJson ?? { ok: false, message: "Bad upstream response" },
{ status: upstreamRes.status, headers: corsHeaders(req) }
);
}