| import { createServer } from "node:http"; |
| import { createReadStream } from "node:fs"; |
| import { stat } from "node:fs/promises"; |
| import { extname, join, normalize, sep } from "node:path"; |
| import { fileURLToPath } from "node:url"; |
|
|
| const port = Number(process.env.PORT ?? 7860); |
| const host = process.env.HOST ?? "0.0.0.0"; |
| const clientDir = fileURLToPath(new URL("../dist/client/", import.meta.url)); |
|
|
| const { default: app } = await import("../dist/server/server.js"); |
|
|
| const contentTypes = { |
| ".css": "text/css; charset=utf-8", |
| ".js": "text/javascript; charset=utf-8", |
| ".svg": "image/svg+xml", |
| ".jpg": "image/jpeg", |
| ".jpeg": "image/jpeg", |
| ".png": "image/png", |
| ".webp": "image/webp", |
| ".ico": "image/x-icon", |
| ".json": "application/json; charset=utf-8", |
| }; |
|
|
| function resolveStaticPath(pathname) { |
| if (!pathname.startsWith("/assets/") && pathname !== "/favicon.svg") { |
| return undefined; |
| } |
|
|
| const relativePath = normalize(decodeURIComponent(pathname).replace(/^\/+/, "")); |
| const filePath = join(clientDir, relativePath); |
| const clientRoot = clientDir.endsWith(sep) ? clientDir : `${clientDir}${sep}`; |
|
|
| if (!filePath.startsWith(clientRoot)) { |
| return undefined; |
| } |
|
|
| return filePath; |
| } |
|
|
| async function serveStaticAsset(req, res, pathname) { |
| const filePath = resolveStaticPath(pathname); |
| if (!filePath) return false; |
|
|
| try { |
| const fileStat = await stat(filePath); |
| if (!fileStat.isFile()) return false; |
|
|
| res.writeHead(200, { |
| "content-type": contentTypes[extname(filePath)] ?? "application/octet-stream", |
| "content-length": fileStat.size, |
| "cache-control": pathname.startsWith("/assets/") |
| ? "public, max-age=31536000, immutable" |
| : "public, max-age=3600", |
| }); |
|
|
| if (req.method === "HEAD") { |
| res.end(); |
| return true; |
| } |
|
|
| createReadStream(filePath).pipe(res); |
| return true; |
| } catch { |
| return false; |
| } |
| } |
|
|
| const server = createServer(async (req, res) => { |
| const origin = `http://${req.headers.host ?? `${host}:${port}`}`; |
| const url = new URL(req.url ?? "/", origin); |
|
|
| if (await serveStaticAsset(req, res, url.pathname)) { |
| return; |
| } |
|
|
| const request = new Request(url, { |
| method: req.method, |
| headers: req.headers, |
| body: req.method === "GET" || req.method === "HEAD" ? undefined : req, |
| duplex: "half", |
| }); |
|
|
| try { |
| const response = await app.fetch(request, {}, {}); |
| res.writeHead(response.status, Object.fromEntries(response.headers)); |
|
|
| if (response.body) { |
| const reader = response.body.getReader(); |
| while (true) { |
| const { done, value } = await reader.read(); |
| if (done) break; |
| res.write(Buffer.from(value)); |
| } |
| } |
|
|
| res.end(); |
| } catch (error) { |
| console.error(error); |
| res.writeHead(500, { "content-type": "text/plain; charset=utf-8" }); |
| res.end("Internal Server Error"); |
| } |
| }); |
|
|
| server.listen(port, host, () => { |
| console.log(`Portfolio listening on http://${host}:${port}`); |
| }); |
|
|