import "server-only"; import { getDefaultStorageConfig } from "@/lib/db/queries"; import { findImageArchiveDownloadTask } from "./image-archive-db"; import { inferOriginalImageUrl } from "@/lib/image-url"; import { getImageDownloadExtension } from "@/lib/image-delivery"; import { sanitizeCanvasDownloadFileName } from "@/lib/canvas/photoshop-safe-download"; /** Resolve the archived original without waiting for a separate PNG conversion. */ export async function resolveOriginalCdnDownload(source: string, name: string, signal: AbortSignal) { const config = await getDefaultStorageConfig(); if (config?.type !== "qiniu-kodo" || !config.isEnabled || !config.publicUrl) return null; const base = new URL(config.publicUrl); const origin = process.env.CANVAS_QINIU_ORIGIN_URL; let target = new URL(source); if (target.origin !== base.origin && (!origin || target.origin !== new URL(origin).origin)) { const task = await findImageArchiveDownloadTask([...new Set([source, inferOriginalImageUrl(source)])]); target = new URL(task?.targetUrl || source); } if (origin && target.origin === new URL(origin).origin && !target.searchParams.has("token")) { target.host = base.host; target.protocol = base.protocol; } if (base.protocol !== "https:" || target.origin !== base.origin || !target.pathname.startsWith(base.pathname.replace(/\/$/, "") + "/")) return null; // A Kodo download token signs the complete URL; adding attname would invalidate it. if (target.searchParams.has("token")) return null; // Only metadata crosses the application server. The browser receives the file // from the CDN, including when cross-origin fetch is disabled by storage CORS. const response = await fetch(target, { method: "HEAD", cache: "no-store", signal: AbortSignal.any([signal, AbortSignal.timeout(10_000)]), }); if (!response.ok) throw new Error(`HTTP ${response.status}`); const contentType = response.headers.get("content-type") || ""; if (!contentType.toLowerCase().startsWith("image/")) throw new Error("Source is not an image"); const extension = getImageDownloadExtension(contentType); if (!extension) return null; const basename = sanitizeCanvasDownloadFileName(name || target.pathname.split("/").pop() || "image", "image") .replace(/\.(?:png|jpe?g|webp|avif|gif|svg|bmp|tiff?)$/i, ""); const filename = `${basename}.${extension}`; target.searchParams.set("attname", filename); return { delivery: "cdn" as const, downloadUrl: target.toString(), filename, bytes: Number(response.headers.get("content-length")) || 0 }; }