Files
2026-09-01 14:10:51 +02:00

48 lines
1.7 KiB
JavaScript

import { createServer } from "node:http";
import { readFile, stat } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"..",
"dist",
),
prefix = "/deep/nested/diagram/",
types = new Map([
[".css", "text/css"],
[".html", "text/html"],
[".js", "text/javascript"],
[".json", "application/json"],
[".webmanifest", "application/manifest+json"],
[".svg", "image/svg+xml"],
[".md", "text/markdown"],
[".txt", "text/plain"],
]),
headers = {
"Content-Security-Policy":
"default-src 'self';base-uri 'self';object-src 'none';script-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;connect-src 'self';worker-src 'self' blob:;manifest-src 'self'",
"Permissions-Policy": "camera=(),microphone=(),geolocation=()",
"Referrer-Policy": "no-referrer",
"X-Content-Type-Options": "nosniff",
};
createServer(async (q, s) => {
try {
const u = new URL(q.url ?? "/", "http://x"),
d = decodeURIComponent(u.pathname),
r = d.startsWith(prefix) ? d.slice(prefix.length) : d.replace(/^\/+/, ""),
n = path.posix.normalize(r || "index.html");
if (n.startsWith("../") || path.isAbsolute(n))
return void s.writeHead(400).end();
let f = path.join(root, n);
if ((await stat(f).catch(() => null))?.isDirectory())
f = path.join(f, "index.html");
s.writeHead(200, {
"Content-Type": types.get(path.extname(f)) ?? "application/octet-stream",
...headers,
});
s.end(await readFile(f));
} catch {
s.writeHead(404).end();
}
}).listen(4222, "127.0.0.1", () => console.log("ready"));