import { createReadStream } from 'node:fs'; import { stat } from 'node:fs/promises'; import { extname } from 'node:path'; import { httpError } from '../http/httpError.mjs'; import { mimeTypes } from './mimeTypes.mjs'; import { resolveInside } from './resolveInside.mjs'; export async function serveFile(response, root, pathname, method) { const filePath = resolveInside(root, pathname); if (!filePath) { throw httpError(403, 'Forbidden'); } const fileStat = await getFileStat(filePath); response.writeHead(200, { 'Content-Length': fileStat.size, 'Content-Type': mimeTypes[extname(filePath).toLowerCase()] || 'application/octet-stream', 'X-Content-Type-Options': 'nosniff', }); if (method === 'HEAD') { response.end(); return; } createReadStream(filePath).pipe(response); } async function getFileStat(filePath) { let fileStat; try { fileStat = await stat(filePath); } catch { throw httpError(404, 'Not found'); } if (!fileStat.isFile()) { throw httpError(404, 'Not found'); } return fileStat; }