Track HiveGrid Cloud planning reference

This commit is contained in:
david committed 2026-06-26 20:48:01 +02:00
1 parent b3d5ea6764
commit e341c5938a
5784 files changed
+1104929 -3

No files matched your search

@@ -0,0 +1,206 @@
// @vitest-environment node
import { describe, expect, test } from "vitest";
import { getHostRoutingRuntimeDecision } from "./host-routing-runtime";
function expectDispatchDecision(request: Request) {
const decision = getHostRoutingRuntimeDecision(request);
expect(decision.type).toBe("dispatch");
if (decision.type !== "dispatch") {
throw new Error(`Expected dispatch decision, received ${decision.type}`);
}
return decision;
}
describe("getHostRoutingRuntimeDecision", () => {
test("dispatches the canonical app host root to the tenant picker route", () => {
const decision = expectDispatchDecision(new Request("http://app.localhost/?from=login#tenants"));
expect(decision.target).toBe("web");
expect(new URL(decision.request.url).pathname).toBe("/");
expect(new URL(decision.request.url).search).toBe("?from=login");
expect(new URL(decision.request.url).hash).toBe("#tenants");
});
test("keeps app host requests on promoted tenant paths for web dispatch", () => {
const decision = expectDispatchDecision(new Request("http://app.localhost/acme/dashboard?tab=activity#events"));
expect(decision.target).toBe("web");
expect(new URL(decision.request.url).pathname).toBe("/acme/dashboard");
expect(new URL(decision.request.url).search).toBe("?tab=activity");
expect(new URL(decision.request.url).hash).toBe("#events");
});
test("dispatches public auth routes on the app host without tenant rewriting", () => {
const decision = expectDispatchDecision(new Request("http://app.localhost/login?redirectTo=%2Facme%2Fdashboard"));
expect(decision.target).toBe("web");
expect(new URL(decision.request.url).pathname).toBe("/login");
expect(new URL(decision.request.url).search).toBe("?redirectTo=%2Facme%2Fdashboard");
});
test("rejects removed public API paths instead of redirecting compatibility routes", () => {
const decision = getHostRoutingRuntimeDecision(new Request("http://app.localhost/api/workflows/run/workflow_1?tenantId=tenant_1"));
expect(decision).toEqual({
type: "reject",
status: 404,
});
});
test("redirects legacy api v1 paths before removed API path rejection", () => {
expect(getHostRoutingRuntimeDecision(new Request("http://app.localhost/api/v1/health?check=deep#status"))).toEqual({
type: "redirect",
status: 308,
location: "http://api.localhost/v1/health?check=deep#status",
});
});
test("lets internal API proxies reach private web API handlers without public redirects", () => {
const decision = expectDispatchDecision(
new Request("http://app.localhost/internal/api/workflows/run/workflow_1?tenantId=tenant_1", {
method: "POST",
headers: {
"x-toolctrl-internal-web-api-proxy": "1",
"x-toolctrl-internal-web-api-proxy-signature": "signed",
"x-api-key": "tenant-api-key",
},
body: JSON.stringify({ name: "Ada" }),
})
);
expect(decision.target).toBe("web");
expect(new URL(decision.request.url).pathname).toBe("/internal/api/workflows/run/workflow_1");
expect(new URL(decision.request.url).search).toBe("?tenantId=tenant_1");
expect(decision.request.headers.get("x-toolctrl-internal-web-api-proxy")).toBe("1");
expect(decision.request.headers.get("x-toolctrl-internal-web-api-proxy-signature")).toBe("signed");
expect(decision.request.headers.get("x-api-key")).toBe("tenant-api-key");
});
test("dispatches canonical admin host requests for web dispatch", () => {
const decision = expectDispatchDecision(new Request("http://admin.localhost/accounts/users?role=owner#active"));
expect(decision.target).toBe("web");
expect(new URL(decision.request.url).pathname).toBe("/accounts/users");
expect(new URL(decision.request.url).search).toBe("?role=owner");
expect(new URL(decision.request.url).hash).toBe("#active");
});
test("keeps canonical admin host routes stable for web dispatch", () => {
const settingsDecision = expectDispatchDecision(new Request("http://admin.localhost/settings/profile?tab=mfa#codes"));
const metricsDataDecision = expectDispatchDecision(new Request("http://admin.localhost/metrics/summary.data?_routes=routes%2Fadmin%2Fmetrics%2Fsummary.__host"));
expect(settingsDecision.target).toBe("web");
expect(new URL(settingsDecision.request.url).pathname).toBe("/settings/profile");
expect(new URL(settingsDecision.request.url).search).toBe("?tab=mfa");
expect(new URL(settingsDecision.request.url).hash).toBe("#codes");
expect(new URL(metricsDataDecision.request.url).pathname).toBe("/metrics/summary.data");
});
test.each([
["/api?tab=overview", "/api"],
["/api/keys?filter=active#keys", "/api/keys"],
["/api/keys/new", "/api/keys/new"],
["/api/keys/api_key_1", "/api/keys/api_key_1"],
["/api/logs", "/api/logs"],
["/api/docs", "/api/docs"],
["/api/credits", "/api/credits"],
["/api/keys.data?_routes=routes%2Fadmin%2Fapi%2Fkeys.__host", "/api/keys.data"],
])("dispatches canonical admin API section route %s to the web runtime", (route, expectedPathname) => {
const decision = expectDispatchDecision(new Request(`http://admin.localhost${route}`));
expect(decision.target).toBe("web");
expect(new URL(decision.request.url).pathname).toBe(expectedPathname);
});
test("redirects API host unversioned aliases to v1 paths before dispatch", () => {
expect(getHostRoutingRuntimeDecision(new Request("http://api.localhost/health?check=deep#status"))).toEqual({
type: "redirect",
status: 308,
location: "http://api.localhost/v1/health?check=deep#status",
});
expect(getHostRoutingRuntimeDecision(new Request("http://api.localhost/accounts?cursor=next"))).toEqual({
type: "redirect",
status: 308,
location: "http://api.localhost/v1/accounts?cursor=next",
});
});
test("redirects public web paths away from the API host", () => {
const decision = getHostRoutingRuntimeDecision(new Request("http://api.localhost/login?redirectTo=%2Facme%2Fdashboard"));
expect(decision).toEqual({
type: "redirect",
status: 308,
location: "http://app.localhost/login?redirectTo=%2Facme%2Fdashboard",
});
});
test("does not double-prefix API internal paths", () => {
const apiDecision = expectDispatchDecision(new Request("http://api.localhost/v1/health?check=deep#status"));
expect(new URL(apiDecision.request.url).pathname).toBe("/v1/health");
});
test("rejects removed root app paths instead of redirecting compatibility routes", () => {
const decision = getHostRoutingRuntimeDecision(new Request("http://localhost/app/acme/settings?tab=profile#billing"));
expect(decision).toEqual({
type: "reject",
status: 404,
});
});
test("rejects removed admin paths on root and app hosts", () => {
expect(getHostRoutingRuntimeDecision(new Request("http://localhost/admin/settings?tab=users#active"))).toEqual({
type: "reject",
status: 404,
});
expect(getHostRoutingRuntimeDecision(new Request("http://app.localhost/admin/settings?tab=users#active"))).toEqual({
type: "reject",
status: 404,
});
});
test("redirects canonical paths away from the wrong host before dispatch", () => {
expect(getHostRoutingRuntimeDecision(new Request("http://app.localhost/dashboard?tab=activity#events"))).toEqual({
type: "redirect",
status: 308,
location: "http://admin.localhost/dashboard?tab=activity#events",
});
expect(getHostRoutingRuntimeDecision(new Request("http://app.localhost/accounts/users?filter=active"))).toEqual({
type: "redirect",
status: 308,
location: "http://admin.localhost/accounts/users?filter=active",
});
expect(getHostRoutingRuntimeDecision(new Request("http://admin.localhost/acme/dashboard?tab=activity#events"))).toEqual({
type: "redirect",
status: 308,
location: "http://app.localhost/acme/dashboard?tab=activity#events",
});
expect(getHostRoutingRuntimeDecision(new Request("http://admin.localhost/acme"))).toEqual({
type: "redirect",
status: 308,
location: "http://app.localhost/acme",
});
expect(getHostRoutingRuntimeDecision(new Request("http://api.localhost/acme"))).toEqual({
type: "redirect",
status: 308,
location: "http://app.localhost/acme",
});
expect(getHostRoutingRuntimeDecision(new Request("http://app.localhost/v1/health"))).toEqual({
type: "redirect",
status: 308,
location: "http://api.localhost/v1/health",
});
});
test("dispatches API operational routes to the API runtime", () => {
const healthDecision = expectDispatchDecision(new Request("http://api.localhost/healthz"));
const readyDecision = expectDispatchDecision(new Request("http://api.localhost/readyz"));
expect(healthDecision.target).toBe("api");
expect(new URL(healthDecision.request.url).pathname).toBe("/healthz");
expect(readyDecision.target).toBe("api");
expect(new URL(readyDecision.request.url).pathname).toBe("/readyz");
});
});
@@ -0,0 +1,85 @@
import { getCanonicalHostRedirectUrl, getHostAwareInternalUrlPath, getHostRoutingContextFromRequest } from "../apps/web/app/utils/app/HostRouting.server";
export type HostRoutingRuntimeDecision =
| { type: "redirect"; status: 308; location: string }
| { type: "reject"; status: 404 }
| { type: "dispatch"; target: "api" | "web"; request: Request };
const internalWebApiProxyHeader = "x-toolctrl-internal-web-api-proxy";
export function getHostRoutingRuntimeDecision(request: Request): HostRoutingRuntimeDecision {
const context = getHostRoutingContextFromRequest(request);
if (isInternalWebApiProxyRequest(request, context)) {
const requestUrl = new URL(request.url);
const rewrittenRequest = rewriteRequestUrl(request, `${requestUrl.pathname}${requestUrl.search}${requestUrl.hash}`);
return {
type: "dispatch",
target: "web",
request: rewrittenRequest,
};
}
if (isRemovedLegacyRoute(request, context)) {
return {
type: "reject",
status: 404,
};
}
const canonicalRedirectUrl = getCanonicalHostRedirectUrl(request);
if (canonicalRedirectUrl) {
return {
type: "redirect",
status: 308,
location: canonicalRedirectUrl,
};
}
const rewrittenRequest = rewriteRequestUrl(request, getRuntimeInternalUrlPath(request, context));
return {
type: "dispatch",
target: context === "api" ? "api" : "web",
request: rewrittenRequest,
};
}
function isInternalWebApiProxyRequest(request: Request, context: ReturnType<typeof getHostRoutingContextFromRequest>) {
if (context !== "app" || request.headers.get(internalWebApiProxyHeader) !== "1") {
return false;
}
const pathname = new URL(request.url).pathname;
return pathname === "/internal/api/usage" || pathname === "/internal/api/stripe.webhooks" || pathname.startsWith("/internal/api/workflows/");
}
function isRemovedLegacyRoute(request: Request, context: ReturnType<typeof getHostRoutingContextFromRequest>) {
const pathname = new URL(request.url).pathname.replace(/\/+$/g, "") || "/";
const isLegacyApiV1Route = pathname === "/api/v1" || pathname.startsWith("/api/v1/");
const isAdminApiSectionRoute = context === "admin" && (pathname === "/api" || pathname.startsWith("/api/")) && !isLegacyApiV1Route;
return (
pathname === "/app" ||
pathname.startsWith("/app/") ||
pathname === "/admin" ||
pathname.startsWith("/admin/") ||
(!isAdminApiSectionRoute && (pathname === "/api" || (pathname.startsWith("/api/") && !isLegacyApiV1Route)))
);
}
function getRuntimeInternalUrlPath(request: Request, context: ReturnType<typeof getHostRoutingContextFromRequest>) {
if (context === "app") {
const url = new URL(request.url);
return `${url.pathname}${url.search}${url.hash}`;
}
return getHostAwareInternalUrlPath(request);
}
function rewriteRequestUrl(request: Request, internalUrlPath: string) {
const url = new URL(request.url);
url.pathname = "/";
url.search = "";
url.hash = "";
const rewrittenUrl = new URL(internalUrlPath, url);
return new Request(rewrittenUrl, request);
}
+5
View File
@@ -0,0 +1,5 @@
{
"name": "@toolctrl/server",
"private": true,
"type": "module"
}
+90
View File
@@ -0,0 +1,90 @@
import { describe, expect, test } from "vitest";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import path from "node:path";
const serverSource = readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), "server.ts"), "utf8");
const rootPackage = JSON.parse(readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"));
const webPackage = JSON.parse(readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "apps", "web", "package.json"), "utf8"));
describe("server runtime routing integration", () => {
test("delegates host routing decisions before API or React Router dispatch", () => {
expect(serverSource).toContain("getHostRoutingRuntimeDecision(request)");
expect(serverSource).toContain('routingDecision.type === "redirect"');
expect(serverSource).toContain('routingDecision.target === "api"');
});
test("uses required web config for fail-fast production startup and listen host/port", () => {
expect(serverSource).toContain('import { loadRequiredWebConfig } from "@toolctrl/config"');
expect(serverSource).toContain("const webConfig = loadRequiredWebConfig()");
expect(serverSource).toContain("const PORT = webConfig.listen.port");
expect(serverSource).toContain("const HOST = webConfig.listen.host");
expect(serverSource).not.toContain("loadWebConfig().config");
expect(serverSource).not.toContain("parsePort(process.env.PORT)");
expect(serverSource).not.toContain("process.env.HOST");
});
test("delegates root start to the web runtime owner", () => {
expect(rootPackage.scripts.start).toBe("pnpm --filter @toolctrl/web start");
expect(webPackage.scripts.start).toContain("node ../../build/server-runtime/server.js");
expect(webPackage.scripts.start).not.toContain("tsx");
expect(rootPackage.scripts.start).not.toContain("tsx");
});
test("resolves web build artifacts independently from caller cwd", () => {
expect(serverSource).toContain("const RUNTIME_DIRECTORY = path.dirname(fileURLToPath(import.meta.url))");
expect(serverSource).toContain('RUNTIME_DIRECTORY.endsWith(path.join("build", "server-runtime"))');
expect(serverSource).toContain('path.join(REPO_ROOT_DIRECTORY, "apps", "web", "build")');
expect(serverSource).toContain('const BUILD_PATH = path.join(WEB_BUILD_DIRECTORY, "server", "index.js")');
expect(serverSource).toContain('const CLIENT_BUILD_DIRECTORY = path.join(WEB_BUILD_DIRECTORY, "client")');
expect(serverSource).not.toContain('path.resolve("build/server/index.js")');
expect(serverSource).not.toContain('path.resolve("build/client")');
});
test("defines idempotent web security headers", () => {
expect(serverSource).toContain("function appendWebSecurityHeaders");
expect(serverSource).toContain("\"Content-Security-Policy\": \"base-uri 'self'; object-src 'none'; frame-ancestors 'self'\"");
expect(serverSource).toContain('"Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"');
expect(serverSource).toContain('"X-Content-Type-Options": "nosniff"');
expect(serverSource).toContain('"Referrer-Policy": "strict-origin-when-cross-origin"');
expect(serverSource).toContain('"X-Frame-Options": "SAMEORIGIN"');
expect(serverSource).toContain('"Permissions-Policy": "camera=(), microphone=(), geolocation=(), payment=()"');
expect(serverSource).toContain('"Cross-Origin-Opener-Policy": "same-origin"');
expect(serverSource).toContain('"Cross-Origin-Resource-Policy": "same-origin"');
expect(serverSource).toContain('"Cross-Origin-Embedder-Policy": "unsafe-none"');
expect(serverSource).toContain('key === "Content-Security-Policy" && hasHeader(headers, key)');
expect(serverSource).toContain("headers.set(key, value)");
expect(serverSource).toContain("headers.setHeader(key, value)");
});
test("applies web security headers to forwarded responses", () => {
expect(serverSource).toMatch(/for \(const \[key, value\] of response\.headers\)[\s\S]*res\.appendHeader\(key, value\);[\s\S]*appendWebSecurityHeaders\(res\);/);
});
test("applies web security headers to static assets without changing cache control", () => {
expect(serverSource).toContain('headers["Cache-Control"] = "public, max-age=31536000, immutable"');
expect(serverSource).toMatch(/function getStaticHeaders[\s\S]*return appendWebSecurityHeaders\(headers\);/);
});
test("sets a 1-day cache for /fonts and /images static assets", () => {
// Hash-named bundles get `immutable` because their URL contains the hash,
// but unhashed brand assets need a shorter TTL or stale-content lingers.
// See docs/improvement-plan/03-scaling-infrastructure/asset-cdn.md.
expect(serverSource).toContain('headers["Cache-Control"] = "public, max-age=86400"');
expect(serverSource).toMatch(/pathname === "\/fonts"[\s\S]*pathname\.startsWith\("\/fonts\/"\)/);
expect(serverSource).toMatch(/pathname === "\/images"[\s\S]*pathname\.startsWith\("\/images\/"\)/);
});
test("wires server diagnostics through the structured logger", () => {
expect(serverSource).toContain('import { createChildLogger, defaultLogger } from "@toolctrl/logger"');
expect(serverSource).toContain('const serverLogger = createChildLogger(defaultLogger, { component: "server" })');
expect(serverSource).toContain('serverLogger.error({ error }, "server request failed")');
expect(serverSource).toContain('serverLogger.info({ host: address, port: PORT }, "server listening")');
expect(serverSource).toContain('serverLogger.error({ error }, "server shutdown failed")');
expect(serverSource).toContain('serverLogger.error({ error }, "static asset stream failed")');
});
test("does not leave active console diagnostics in the server runtime", () => {
expect(serverSource).not.toMatch(/console\.(?:log|error|warn|info)\s*\(/);
});
});
+344
View File
@@ -0,0 +1,344 @@
import { ServerResponse, createServer, type IncomingMessage } from "node:http";
import { createReadStream } from "node:fs";
import { stat } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import type { ServerBuild } from "react-router";
import { loadRequiredWebConfig } from "@toolctrl/config";
import { createChildLogger, defaultLogger } from "@toolctrl/logger";
import { app as apiApp } from "../apps/api/src/app";
import { getHostRoutingRuntimeDecision } from "./host-routing-runtime";
process.env.NODE_ENV = process.env.NODE_ENV ?? "production";
const RUNTIME_DIRECTORY = path.dirname(fileURLToPath(import.meta.url));
const REPO_ROOT_DIRECTORY = RUNTIME_DIRECTORY.endsWith(path.join("build", "server-runtime"))
? path.resolve(RUNTIME_DIRECTORY, "..", "..")
: path.resolve(RUNTIME_DIRECTORY, "..");
const WEB_BUILD_DIRECTORY = process.env.WEB_BUILD_DIRECTORY
? path.resolve(process.env.WEB_BUILD_DIRECTORY)
: path.join(REPO_ROOT_DIRECTORY, "apps", "web", "build");
const BUILD_PATH = path.join(WEB_BUILD_DIRECTORY, "server", "index.js");
const CLIENT_BUILD_DIRECTORY = path.join(WEB_BUILD_DIRECTORY, "client");
const ALLOWED_STATIC_ASSET_EXTENSIONS = new Set([
".avif",
".css",
".eot",
".gif",
".ico",
".jpeg",
".jpg",
".js",
".json",
".mjs",
".png",
".svg",
".ttf",
".txt",
".webmanifest",
".webp",
".woff",
".woff2",
".xml",
]);
const webConfig = loadRequiredWebConfig();
const PORT = webConfig.listen.port;
const HOST = webConfig.listen.host;
const serverLogger = createChildLogger(defaultLogger, { component: "server" });
const [{ createRequestHandler }, { createReadableStreamFromReadable, writeReadableStreamToWritable }] = await Promise.all([
import("react-router"),
import("@react-router/node"),
]);
const build = (await import(pathToFileURL(BUILD_PATH).href)) as ServerBuild;
const handleReactRouterRequest = createRequestHandler(build, process.env.NODE_ENV);
type NodeRequestInit = RequestInit & { duplex?: "half" };
const server = createServer(async (req, res) => {
try {
if (await serveStaticAsset(req, res)) {
return;
}
const request = createWebRequest(req, res);
const routingDecision = getHostRoutingRuntimeDecision(request);
if (routingDecision.type === "redirect") {
await sendWebResponse(
res,
new Response(null, {
status: routingDecision.status,
headers: { Location: routingDecision.location },
})
);
return;
}
if (routingDecision.type === "reject") {
await sendWebResponse(res, new Response("Not Found", { status: routingDecision.status }));
return;
}
if (routingDecision.target === "web" && isWebOperationalRoute(request)) {
await sendWebResponse(res, await handleReactRouterRequest(request));
return;
}
const response = routingDecision.target === "api" ? await apiApp.fetch(routingDecision.request) : await handleReactRouterRequest(routingDecision.request);
await sendWebResponse(res, response);
} catch (error) {
serverLogger.error({ error }, "server request failed");
if (!res.headersSent) {
res.statusCode = 500;
res.setHeader("Content-Type", "text/plain; charset=utf-8");
}
res.end("Internal Server Error");
}
});
server.listen(PORT, HOST, () => {
const address = HOST ?? getLocalAddress() ?? "localhost";
serverLogger.info({ host: address, port: PORT }, "server listening");
});
for (const signal of ["SIGTERM", "SIGINT"] as const) {
process.once(signal, () => {
server.close((error) => {
if (error) {
serverLogger.error({ error }, "server shutdown failed");
process.exitCode = 1;
}
});
});
}
async function serveStaticAsset(req: IncomingMessage, res: ServerResponse) {
if (req.method !== "GET" && req.method !== "HEAD") {
return false;
}
const requestUrl = new URL(req.url ?? "/", "http://internal");
const filePath = getClientFilePath(requestUrl.pathname);
if (!filePath) {
return false;
}
const fileStat = await stat(filePath).catch(() => null);
if (!fileStat?.isFile()) {
return false;
}
const headers = getStaticHeaders(filePath, requestUrl.pathname);
res.writeHead(200, headers);
if (req.method === "HEAD") {
res.end();
return true;
}
createReadStream(filePath)
.on("error", (error) => {
serverLogger.error({ error }, "static asset stream failed");
if (!res.headersSent) {
res.writeHead(500);
}
res.end();
})
.pipe(res);
return true;
}
function getClientFilePath(pathname: string) {
let decodedPathname: string;
try {
decodedPathname = decodeURIComponent(pathname);
} catch {
return null;
}
const relativePath = decodedPathname.replace(/^\/+/, "");
if (!relativePath) {
return null;
}
if (!ALLOWED_STATIC_ASSET_EXTENSIONS.has(path.extname(relativePath).toLowerCase())) {
return null;
}
const filePath = path.resolve(CLIENT_BUILD_DIRECTORY, relativePath);
if (filePath !== CLIENT_BUILD_DIRECTORY && !filePath.startsWith(`${CLIENT_BUILD_DIRECTORY}${path.sep}`)) {
return null;
}
return filePath;
}
function createWebRequest(req: IncomingMessage, res: ServerResponse) {
const protocol = req.headers["x-forwarded-proto"]?.toString().split(",")[0]?.trim() || "http";
const host = req.headers.host || "localhost";
const url = new URL(req.url ?? "/", `${protocol}://${host}`);
const controller = new AbortController();
res.on("close", () => {
controller.abort();
});
const init: NodeRequestInit = {
method: req.method,
headers: createWebHeaders(req.headers),
signal: controller.signal,
};
if (req.method !== "GET" && req.method !== "HEAD") {
init.body = createReadableStreamFromReadable(req);
init.duplex = "half";
}
return new Request(url, init);
}
function isWebOperationalRoute(request: Request) {
const { pathname } = new URL(request.url);
return pathname === "/healthz" || pathname === "/readyz" || pathname === "/healthcheck";
}
function createWebHeaders(headers: IncomingMessage["headers"]) {
const webHeaders = new Headers();
for (const [key, value] of Object.entries(headers)) {
if (Array.isArray(value)) {
for (const item of value) {
webHeaders.append(key, item);
}
} else if (value !== undefined) {
webHeaders.set(key, value);
}
}
return webHeaders;
}
async function sendWebResponse(res: ServerResponse, response: Response) {
res.statusCode = response.status;
res.statusMessage = response.statusText;
for (const [key, value] of response.headers) {
res.appendHeader(key, value);
}
appendWebSecurityHeaders(res);
if (!response.body) {
res.end();
return;
}
await writeReadableStreamToWritable(response.body, res);
}
function appendWebSecurityHeaders(headers: Headers): Headers;
function appendWebSecurityHeaders(headers: Record<string, string>): Record<string, string>;
function appendWebSecurityHeaders(headers: ServerResponse): ServerResponse;
function appendWebSecurityHeaders(headers: Headers | Record<string, string> | ServerResponse) {
const securityHeaders: Record<string, string> = {
"Content-Security-Policy": "base-uri 'self'; object-src 'none'; frame-ancestors 'self'",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin-when-cross-origin",
"X-Frame-Options": "SAMEORIGIN",
"Permissions-Policy": "camera=(), microphone=(), geolocation=(), payment=()",
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Resource-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "unsafe-none",
};
if (webConfig.routing.protocol === "https") {
securityHeaders["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";
}
for (const [key, value] of Object.entries(securityHeaders)) {
if (key === "Content-Security-Policy" && hasHeader(headers, key)) {
continue;
}
if (headers instanceof Headers) {
headers.set(key, value);
} else if (headers instanceof ServerResponse) {
headers.setHeader(key, value);
} else {
headers[key] = value;
}
}
return headers;
}
function hasHeader(headers: Headers | Record<string, string> | ServerResponse, key: string) {
if (headers instanceof Headers) {
return headers.has(key);
}
if (headers instanceof ServerResponse) {
return headers.hasHeader(key);
}
const normalizedKey = key.toLowerCase();
return Object.keys(headers).some((candidate) => candidate.toLowerCase() === normalizedKey);
}
function getStaticHeaders(filePath: string, pathname: string) {
const headers: Record<string, string> = {
"Content-Type": getContentType(filePath),
};
// Cache-Control strategy aligned with docs/ops/asset-cdn.md:
// * /assets/* → Vite-hashed, safe to cache forever (1 year, immutable)
// * /fonts/* → static brand assets, 1 day
// * /images/* → static brand assets, 1 day
// Anything else (HTML / loader responses / favicons) keeps the default
// (no Cache-Control here — the loader / entry.server is in charge).
if (pathname === "/assets" || pathname.startsWith("/assets/")) {
headers["Cache-Control"] = "public, max-age=31536000, immutable";
} else if (pathname === "/fonts" || pathname.startsWith("/fonts/") || pathname === "/images" || pathname.startsWith("/images/")) {
headers["Cache-Control"] = "public, max-age=86400";
}
return appendWebSecurityHeaders(headers);
}
function getContentType(filePath: string) {
switch (path.extname(filePath).toLowerCase()) {
case ".css":
return "text/css; charset=utf-8";
case ".js":
case ".mjs":
return "text/javascript; charset=utf-8";
case ".json":
case ".webmanifest":
return "application/json; charset=utf-8";
case ".svg":
return "image/svg+xml";
case ".png":
return "image/png";
case ".jpg":
case ".jpeg":
return "image/jpeg";
case ".gif":
return "image/gif";
case ".ico":
return "image/x-icon";
case ".txt":
return "text/plain; charset=utf-8";
case ".html":
return "text/html; charset=utf-8";
case ".woff":
return "font/woff";
case ".woff2":
return "font/woff2";
case ".ttf":
return "font/ttf";
default:
return "application/octet-stream";
}
}
function getLocalAddress() {
return Object.values(os.networkInterfaces())
.flat()
.find((entry) => entry && String(entry.family).includes("4") && !entry.internal)?.address;
}