27 lines
1.7 KiB
JavaScript
27 lines
1.7 KiB
JavaScript
import http from "node:http";
|
|
import { readFile } from "node:fs/promises";
|
|
import path from "node:path";
|
|
const root = path.resolve("apps/web/dist");
|
|
http.createServer(async (req, res) => {
|
|
if (!/^localhost(?::\d+)?$|^127\.0\.0\.1(?::\d+)?$/.test(req.headers.host ?? "")) { res.writeHead(403).end(); return; }
|
|
if (req.headers.origin && req.headers.origin !== `http://${req.headers.host}`) { res.writeHead(403).end(); return; }
|
|
if (req.url?.startsWith("/api/") || req.url === "/health") {
|
|
const upstream = http.request({ hostname: "127.0.0.1", port: 3001, path: req.url, method: req.method, headers: { ...req.headers, host: "127.0.0.1:3001" } }, response => {
|
|
res.writeHead(response.statusCode ?? 502, response.headers); response.pipe(res);
|
|
});
|
|
upstream.on("error", () => { if (!res.headersSent) res.writeHead(502); res.end(); });
|
|
res.on("close", () => upstream.destroy());
|
|
req.pipe(upstream); return;
|
|
}
|
|
try {
|
|
if (req.method !== "GET" && req.method !== "HEAD") { res.writeHead(405).end(); return; }
|
|
const pathname = decodeURIComponent(new URL(req.url ?? "/", "http://localhost").pathname);
|
|
const file = path.resolve(root, `.${pathname === "/" ? "/index.html" : pathname}`);
|
|
if (!file.startsWith(root + path.sep)) { res.writeHead(403).end(); return; }
|
|
const bytes = await readFile(file);
|
|
const types = { ".html": "text/html", ".js": "text/javascript", ".css": "text/css", ".svg": "image/svg+xml" };
|
|
res.writeHead(200, { "content-type": types[path.extname(file)] ?? "application/octet-stream", "x-content-type-options": "nosniff" });
|
|
res.end(req.method === "HEAD" ? undefined : bytes);
|
|
} catch { res.writeHead(404).end(); }
|
|
}).listen(5173, "0.0.0.0");
|