Files
spsays-training/app/api/share/route.ts
T

58 lines
1.6 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
// Same-origin proxy for the URL-shortener create endpoint. Client components
// (text-selection toolbar, share modal) call /api/share so the actual BFF
// request happens server-side — this is the only way to read `BFF_URL`,
// since Next.js does not expose non-`NEXT_PUBLIC_` env vars to the browser
// bundle. Same pattern as /api/search.
const BFF_BASE = process.env.BFF_URL || "http://localhost:8080";
export async function POST(request: NextRequest) {
let body: unknown;
try {
body = await request.json();
} catch {
return NextResponse.json(
{ success: false, error: { code: 400, message: "invalid JSON body" } },
{ status: 400 },
);
}
const url =
body && typeof body === "object" && "url" in body
? (body as { url: unknown }).url
: null;
if (typeof url !== "string" || !url.startsWith("/")) {
return NextResponse.json(
{
success: false,
error: { code: 400, message: "url must be a same-site path" },
},
{ status: 400 },
);
}
try {
const res = await fetch(new URL("/api/v1/share", BFF_BASE).toString(), {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ url }),
cache: "no-store",
});
const text = await res.text();
return new NextResponse(text, {
status: res.status,
headers: { "Content-Type": "application/json" },
});
} catch {
return NextResponse.json(
{ success: false, error: { code: 502, message: "BFF unreachable" } },
{ status: 502 },
);
}
}