import { readFile } from "fs/promises"; import path from "path"; import { getMediaDir } from "../../../lib/cms"; const CONTENT_TYPES: Record = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp", ".svg": "image/svg+xml", }; // Openbaar (geen sessie): afbeeldingen voor de publieke website, via het CMS // geüpload naar het /data-volume. De CSP-sandbox voorkomt dat een SVG met // script iets kan op dit domein, waar ook het beheer draait. export async function GET(_request: Request, { params }: { params: Promise<{ filename: string }> }) { const { filename } = await params; // Alleen een kale bestandsnaam (geen path traversal) if (filename.includes("/") || filename.includes("\\") || filename.includes("..")) { return new Response("Ongeldige bestandsnaam", { status: 400 }); } const contentType = CONTENT_TYPES[path.extname(filename).toLowerCase()]; if (!contentType) return new Response("Niet ondersteund bestandstype", { status: 400 }); let buffer: Buffer; try { buffer = await readFile(path.join(getMediaDir(), filename)); } catch { return new Response("Niet gevonden", { status: 404 }); } return new Response(new Uint8Array(buffer), { headers: { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable", "Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; sandbox", "X-Content-Type-Options": "nosniff", }, }); }