Files
healer-man/server/bundled-content.mjs
T
2026-09-11 14:26:15 -04:00

55 lines
2.6 KiB
JavaScript

import { createReadStream, readFileSync } from "node:fs";
import path from "node:path";
import { pipeline } from "node:stream";
import { createGunzip } from "node:zlib";
export function contentMimeType(logicalPath) {
return ({
".glb": "model/gltf-binary", ".json": "application/json", ".js": "text/javascript",
".wasm": "application/wasm", ".ktx2": "image/ktx2", ".png": "image/png",
".webp": "image/webp", ".avif": "image/avif", ".svg": "image/svg+xml",
".mp3": "audio/mpeg", ".ogg": "audio/ogg", ".wav": "audio/wav", ".webm": "video/webm",
})[path.extname(logicalPath)] ?? "application/octet-stream";
}
function acceptsGzip(value = "") {
const encodings = new Map(String(value).split(",").map((entry) => {
const [name, ...parameters] = entry.trim().toLowerCase().split(";");
const quality = parameters.find((part) => part.trim().startsWith("q="));
return [name, quality ? Number(quality.trim().slice(2)) : 1];
}));
return (encodings.get("gzip") ?? encodings.get("*") ?? 0) > 0;
}
/** Resolve logical URLs to one immutable bundled object without expanding it on disk. */
export function createBundledContentHandler(root) {
let manifest;
return (request, response, pathname) => {
if (!["GET", "HEAD"].includes(request.method) || !/^\/(assets|basis|data)\//.test(pathname)) return false;
if (manifest === undefined) {
try { manifest = JSON.parse(readFileSync(path.join(root, "content/bootstrap-manifest.json"), "utf8")); }
catch (error) { if (error.code !== "ENOENT") throw error; manifest = null; }
}
const entry = manifest?.files[pathname];
if (!entry) return false;
const object = entry.download ?? entry;
if (!/^\/content\/bundled\/[a-f0-9]{64}\.[a-z0-9]+(?:\.g(?:z|zip))?$/.test(object.url)) return false;
const encoded = entry.download?.encoding === "gzip";
const sendGzip = encoded && acceptsGzip(request.headers["accept-encoding"]);
response.writeHead(200, {
"Content-Type": contentMimeType(pathname),
"Content-Length": sendGzip ? object.bytes : entry.bytes,
"Cache-Control": "public, max-age=3600",
"X-Content-Type-Options": "nosniff",
Vary: "Accept-Encoding",
...(sendGzip ? { "Content-Encoding": "gzip" } : {}),
});
if (request.method === "HEAD") { response.end(); return true; }
const stream = createReadStream(path.join(root, object.url.slice(1)));
const done = (error) => { if (error) response.destroy(error); };
if (encoded && !sendGzip) pipeline(stream, createGunzip(), response, done);
else pipeline(stream, response, done);
return true;
};
}