Files
horizon-airdef/website/serve.mjs
T
Ludovic Marie b3755bd6b1 website: privacy page for opt-in data collection
/privacy says what the launcher may send when a player allows it (performance
summaries, crash and bug reports, benchmark uploads), why, on what basis,
where it is kept and for how long, and how to delete it. The footer links it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 02:59:29 +02:00

28 lines
1.4 KiB
JavaScript

// A dependency-free static server for dist/, for local checks (`npm run dev`).
// Railway uses Caddy instead (see Dockerfile).
import { createServer } from "node:http";
import { readFile, stat } from "node:fs/promises";
import { join, extname, normalize } from "node:path";
import { fileURLToPath } from "node:url";
const root = join(fileURLToPath(new URL(".", import.meta.url)), "dist");
const types = { ".html": "text/html; charset=utf-8", ".css": "text/css", ".js": "text/javascript", ".webp": "image/webp", ".png": "image/png", ".svg": "image/svg+xml", ".woff2": "font/woff2", ".txt": "text/plain; charset=utf-8", ".md": "text/plain; charset=utf-8", ".json": "application/json" };
const port = Number(process.env.PORT) || 4173;
createServer(async (req, res) => {
let path = normalize(decodeURIComponent(new URL(req.url, "http://x").pathname)).replace(/^(\.\.[/\\])+/, "");
if (path.endsWith("/")) path += "index.html";
// /privacy is privacy.html, as the Caddyfile rewrites it.
if (!extname(path)) path += ".html";
let file = join(root, path);
let status = 200;
try {
if (!(await stat(file)).isFile()) throw 0;
} catch {
file = join(root, "404.html");
status = 404;
}
res.writeHead(status, { "Content-Type": types[extname(file)] || "application/octet-stream" });
res.end(await readFile(file));
}).listen(port, () => console.log(`http://localhost:${port}`));