Source code

Revision control

Copy as Markdown

Other Tools

import * as fs from "fs";
import * as http from "http";
import * as path from "path";
const MIME_TYPES = {
default: "application/octet-stream",
html: "text/html; charset=UTF-8",
js: "application/javascript; charset=UTF-8",
mjs: "application/javascript; charset=UTF-8",
css: "text/css",
png: "image/png",
jpg: "image/jpg",
gif: "image/gif",
ico: "image/x-icon",
svg: "image/svg+xml",
};
const STATIC_PATH = path.join(process.cwd(), "./");
const toBool = [() => true, () => false];
export default function serve(port) {
if (!port)
throw new Error("Port is required");
const prepareFile = async (url) => {
const paths = [STATIC_PATH, url];
if (url.endsWith("/"))
paths.push("index.html");
const filePath = path.join(...paths);
const pathTraversal = !filePath.startsWith(STATIC_PATH);
const exists = await fs.promises.access(filePath).then(...toBool);
const found = !pathTraversal && exists;
const streamPath = found ? filePath : `${STATIC_PATH}/index.html`;
const ext = path.extname(streamPath).substring(1).toLowerCase();
const stream = fs.createReadStream(streamPath);
return { found, ext, stream };
};
const server = http
.createServer(async (req, res) => {
const file = await prepareFile(req.url);
const statusCode = file.found ? 200 : 404;
const mimeType = MIME_TYPES[file.ext] || MIME_TYPES.default;
res.writeHead(statusCode, { "Content-Type": mimeType });
file.stream.pipe(res);
})
.listen(port);
console.log(`Server running at http://127.0.0.1:${port}/`);
return server;
}