66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { NextResponse } from "next/server";
|
|
import { getSiteSettings } from "@/lib/db/queries";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
export const revalidate = 0;
|
|
|
|
const DEFAULT_CONTENT_TYPE = "image/x-icon";
|
|
|
|
function noStoreHeaders(contentType: string) {
|
|
return {
|
|
"Content-Type": contentType,
|
|
"Cache-Control": "no-store, no-cache, must-revalidate, proxy-revalidate",
|
|
Pragma: "no-cache",
|
|
Expires: "0",
|
|
};
|
|
}
|
|
|
|
function inferContentType(url: string) {
|
|
const lower = url.toLowerCase();
|
|
if (lower.endsWith(".png")) return "image/png";
|
|
if (lower.endsWith(".svg")) return "image/svg+xml";
|
|
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
|
|
if (lower.endsWith(".webp")) return "image/webp";
|
|
return DEFAULT_CONTENT_TYPE;
|
|
}
|
|
|
|
async function readLocalFallbackFavicon() {
|
|
const file = await readFile(join(process.cwd(), "app", "favicon.ico"));
|
|
return new NextResponse(file, {
|
|
status: 200,
|
|
headers: noStoreHeaders(DEFAULT_CONTENT_TYPE),
|
|
});
|
|
}
|
|
|
|
export async function GET() {
|
|
try {
|
|
const settings = await getSiteSettings();
|
|
const faviconUrl = String(settings?.favicon || "").trim();
|
|
|
|
if (!faviconUrl) {
|
|
return await readLocalFallbackFavicon();
|
|
}
|
|
|
|
const targetUrl = `${faviconUrl}${faviconUrl.includes("?") ? "&" : "?"}v=${Date.now()}`;
|
|
const upstream = await fetch(targetUrl, { cache: "no-store" });
|
|
|
|
if (!upstream.ok) {
|
|
return await readLocalFallbackFavicon();
|
|
}
|
|
|
|
const buffer = await upstream.arrayBuffer();
|
|
const contentType =
|
|
upstream.headers.get("content-type") || inferContentType(faviconUrl);
|
|
|
|
return new NextResponse(buffer, {
|
|
status: 200,
|
|
headers: noStoreHeaders(contentType),
|
|
});
|
|
} catch (_error) {
|
|
return await readLocalFallbackFavicon();
|
|
}
|
|
}
|