18 lines
1.1 KiB
JavaScript
18 lines
1.1 KiB
JavaScript
// Dev server: `node tools/serve.mjs [port]`, serves web/ over http://localhost (mic needs a secure context; localhost qualifies).
|
|
import http from 'node:http';
|
|
import { readFile } from 'node:fs/promises';
|
|
import { extname, join, normalize } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const root = join(fileURLToPath(new URL('.', import.meta.url)), '..');
|
|
const types = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json' };
|
|
const port = +(process.argv[2] || 8080);
|
|
http.createServer(async (req, res) => {
|
|
const p = normalize(decodeURIComponent(new URL(req.url, 'http://x').pathname)).replace(/^(\.\.[/\\])+/, '');
|
|
try {
|
|
const f = join(root, p.endsWith('/') ? p + 'index.html' : p);
|
|
if (!f.startsWith(root)) throw new Error('outside root');
|
|
const body = await readFile(f);
|
|
res.writeHead(200, { 'content-type': types[extname(f)] || 'application/octet-stream' }).end(body);
|
|
} catch { res.writeHead(404).end('not found'); }
|
|
}).listen(port, '127.0.0.1', () => console.log(`Perlines on http://localhost:${port}/`));
|