Your Name ec8959af19
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
修复favicon配置不生效并改为动态拉取
2026-02-14 15:33:48 +08:00

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();
}
}