49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
import { fetchWithTimeout } from "@/lib/helpers/fetchWithTimeout";
|
|
import { NextRequest, NextResponse } from "next/server";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
export const revalidate = 0;
|
|
|
|
const CACHE_MAX_AGE = "public, max-age=3600";
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const url = request.nextUrl.searchParams.get("url");
|
|
if (!url) {
|
|
return NextResponse.json({ error: "url is required" }, { status: 400 });
|
|
}
|
|
try {
|
|
const parsed = new URL(url);
|
|
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
return NextResponse.json({ error: "Invalid URL" }, { status: 400 });
|
|
}
|
|
const res = await fetchWithTimeout(url, {
|
|
timeoutMs: 15_000,
|
|
headers: { Accept: "image/svg+xml, text/xml, text/plain" },
|
|
});
|
|
if (!res.ok) {
|
|
return NextResponse.json(
|
|
{ error: "Failed to fetch SVG" },
|
|
{ status: res.status }
|
|
);
|
|
}
|
|
const text = await res.text();
|
|
if (!text.trim().toLowerCase().includes("<svg")) {
|
|
return NextResponse.json(
|
|
{ error: "Response is not SVG" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
return new NextResponse(text, {
|
|
headers: {
|
|
"Content-Type": "image/svg+xml",
|
|
"Cache-Control": CACHE_MAX_AGE,
|
|
},
|
|
});
|
|
} catch {
|
|
return NextResponse.json(
|
|
{ error: "Failed to fetch SVG" },
|
|
{ status: 502 }
|
|
);
|
|
}
|
|
}
|