58 lines
1.6 KiB
TypeScript
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 },
|
|
);
|
|
}
|
|
}
|