import { createReadStream, existsSync, statSync } from 'node:fs'; import { extname, isAbsolute, join, normalize } from 'node:path'; import { createServer } from 'node:http'; import { Readable } from 'node:stream'; const port = Number(process.env.PORT ?? 5173); const distDirName = process.env.APP_DIST_DIR ?? 'app-dist'; const rootDir = normalize(isAbsolute(distDirName) ? distDirName : join(process.cwd(), distDirName)); const workServerUrl = new URL(process.env.WORK_SERVER_URL ?? 'http://127.0.0.1:3100'); const proxyPrefixes = ['/api', '/.codex_chat']; const mimeTypes = { '.css': 'text/css; charset=utf-8', '.html': 'text/html; charset=utf-8', '.ico': 'image/x-icon', '.js': 'text/javascript; charset=utf-8', '.json': 'application/json; charset=utf-8', '.mjs': 'text/javascript; charset=utf-8', '.png': 'image/png', '.svg': 'image/svg+xml', '.txt': 'text/plain; charset=utf-8', '.webmanifest': 'application/manifest+json; charset=utf-8', '.woff2': 'font/woff2', }; function looksLikeStaticAsset(requestedPath) { const normalizedPath = requestedPath.split('?')[0] ?? requestedPath; const extension = extname(normalizedPath); return extension.length > 0; } function resolvePath(urlPath) { const decodedPath = decodeURIComponent(urlPath.split('?')[0] || '/'); const requestedPath = decodedPath === '/' ? '/index.html' : decodedPath; const absolutePath = normalize(join(rootDir, requestedPath)); if (!absolutePath.startsWith(rootDir)) { return null; } if (existsSync(absolutePath) && statSync(absolutePath).isFile()) { return absolutePath; } if (looksLikeStaticAsset(requestedPath)) { return null; } return join(rootDir, 'index.html'); } function shouldProxyRequest(urlPath = '/') { return proxyPrefixes.some((prefix) => urlPath === prefix || urlPath.startsWith(`${prefix}/`)); } function readRequestBody(request) { return new Promise((resolve, reject) => { const chunks = []; request.on('data', (chunk) => { chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); }); request.on('end', () => { resolve(chunks.length > 0 ? Buffer.concat(chunks) : null); }); request.on('error', reject); }); } async function proxyRequest(request, response) { const targetUrl = new URL(request.url ?? '/', workServerUrl); const headers = new Headers(); Object.entries(request.headers).forEach(([key, value]) => { if (value == null || key.toLowerCase() === 'host' || key.toLowerCase() === 'connection') { return; } if (Array.isArray(value)) { value.forEach((item) => headers.append(key, item)); return; } headers.set(key, value); }); const method = request.method ?? 'GET'; const body = method === 'GET' || method === 'HEAD' ? undefined : await readRequestBody(request); try { const upstreamResponse = await fetch(targetUrl, { method, headers, body, }); response.writeHead( upstreamResponse.status, Object.fromEntries(upstreamResponse.headers.entries()), ); if (!upstreamResponse.body) { response.end(); return; } Readable.fromWeb(upstreamResponse.body).pipe(response); } catch (error) { response.writeHead(502, { 'Content-Type': 'application/json; charset=utf-8' }); response.end( JSON.stringify({ message: error instanceof Error ? error.message : 'Failed to proxy request to work server.', }), ); } } const server = createServer(async (request, response) => { if (shouldProxyRequest(request.url ?? '/')) { await proxyRequest(request, response); return; } const resolvedPath = resolvePath(request.url ?? '/'); if (!resolvedPath || !existsSync(resolvedPath)) { response.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' }); response.end('Not Found'); return; } const extension = extname(resolvedPath); const contentType = mimeTypes[extension] ?? 'application/octet-stream'; response.writeHead(200, { 'Content-Type': contentType, 'Cache-Control': extension === '.html' ? 'no-cache' : 'public, max-age=31536000, immutable', }); createReadStream(resolvedPath).pipe(response); }); server.listen(port, '0.0.0.0', () => { console.log(`${distDirName} server listening on http://0.0.0.0:${port}`); });