codexmobile-relay / server /relay-http-static.js
Codex
deploy: CodexMobile Relay
90f0300
Raw
History Blame Contribute Delete
3.24 kB
import fs from 'node:fs/promises';
import path from 'node:path';
import { gzipSync } from 'node:zlib';
const mimeTypes = new Map([
['.html', 'text/html; charset=utf-8'],
['.js', 'text/javascript; charset=utf-8'],
['.css', 'text/css; charset=utf-8'],
['.json', 'application/json; charset=utf-8'],
['.webmanifest', 'application/manifest+json; charset=utf-8'],
['.svg', 'image/svg+xml'],
['.png', 'image/png'],
['.jpg', 'image/jpeg'],
['.jpeg', 'image/jpeg'],
['.webp', 'image/webp'],
['.ico', 'image/x-icon']
]);
const compressibleExtensions = new Set(['.html', '.js', '.css', '.json', '.webmanifest', '.svg']);
function sendText(res, status, text, headers = {}) {
const body = Buffer.from(String(text || ''));
res.writeHead(status, {
'content-type': 'text/plain; charset=utf-8',
'content-length': body.length,
...headers
});
res.end(body);
}
function acceptsGzip(req) {
return /\bgzip\b/i.test(req.headers['accept-encoding'] || '');
}
function staticCacheControl(ext, filePath = '') {
if (ext === '.html') {
return 'no-store';
}
return filePath.split(path.sep).join('/').includes('/assets/')
? 'public, max-age=31536000, immutable'
: 'public, max-age=3600';
}
function sendStaticContent(req, res, status, content, headers, ext) {
let body = content;
const nextHeaders = { ...headers };
if (content.length >= 1024 && compressibleExtensions.has(ext) && acceptsGzip(req)) {
body = gzipSync(content);
nextHeaders['content-encoding'] = 'gzip';
nextHeaders.vary = nextHeaders.vary ? `${nextHeaders.vary}, Accept-Encoding` : 'Accept-Encoding';
}
nextHeaders['content-length'] = body.length;
res.writeHead(status, nextHeaders);
res.end(body);
}
export async function serveStatic(req, res, url, clientDist) {
let requestedPath = '';
try {
requestedPath = decodeURIComponent(url.pathname);
} catch {
sendText(res, 400, 'Bad request');
return;
}
if (requestedPath === '/') {
requestedPath = '/index.html';
}
const candidate = path.normalize(path.join(clientDist, requestedPath));
if (candidate !== clientDist && !candidate.startsWith(`${clientDist}${path.sep}`)) {
sendText(res, 403, 'Forbidden');
return;
}
try {
const stat = await fs.stat(candidate);
const filePath = stat.isDirectory() ? path.join(candidate, 'index.html') : candidate;
const ext = path.extname(filePath);
const content = await fs.readFile(filePath);
sendStaticContent(req, res, 200, content, {
'content-type': mimeTypes.get(ext) || 'application/octet-stream',
'cache-control': staticCacheControl(ext, filePath),
'x-content-type-options': 'nosniff'
}, ext);
} catch {
await serveStaticFallback(req, res, clientDist);
}
}
async function serveStaticFallback(req, res, clientDist) {
const indexPath = path.join(clientDist, 'index.html');
try {
const content = await fs.readFile(indexPath);
sendStaticContent(req, res, 200, content, {
'content-type': 'text/html; charset=utf-8',
'cache-control': 'no-store',
'x-content-type-options': 'nosniff'
}, '.html');
} catch {
sendText(res, 200, 'CodexMobile relay is running. Build the PWA with: npm run build');
}
}