import { readFile } from "fs/promises"; import { NextResponse } from "next/server"; import path from "path"; import { resolveMediaUploadPath } from "@/lib/media-storage"; type MediaFileRouteProps = { params: Promise<{ segments: string[]; }>; }; export const dynamic = "force-dynamic"; const CONTENT_TYPES: Record = { ".ico": "image/x-icon", ".gif": "image/gif", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".webp": "image/webp", ".svg": "image/svg+xml", ".pdf": "application/pdf", }; export async function GET(_: Request, { params }: MediaFileRouteProps) { const { segments } = await params; const relativePath = segments.join("/"); const publicPath = `/uploads/media/${relativePath}`; try { const absolutePath = resolveMediaUploadPath(publicPath); const fileBuffer = await readFile(absolutePath); const extension = path.extname(absolutePath).toLowerCase(); const contentType = CONTENT_TYPES[extension]; if (!contentType) { return new NextResponse("Not Found", { status: 404 }); } const headers: Record = { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable", "X-Content-Type-Options": "nosniff", }; // SVG is an active document type: sandbox it so an uploaded file can never // run script or reach our origin even if it is opened directly. if (extension === ".svg") { headers["Content-Security-Policy"] = "default-src 'none'; style-src 'unsafe-inline'; sandbox"; } if (extension === ".pdf") { headers["Content-Disposition"] = "inline"; } return new NextResponse(new Uint8Array(fileBuffer), { status: 200, headers }); } catch { return new NextResponse("Not Found", { status: 404, }); } }