Files
2026-09-15 20:37:49 +03:30

22 lines
1.6 KiB
JavaScript

import { createServer } from 'node:http';
import { createReadStream, existsSync } from 'node:fs';
import { stat } from 'node:fs/promises';
import { resolve, sep, extname } from 'node:path';
const root=resolve('out');
if(!existsSync(root)){console.error('Run npm run build before npm start.');process.exit(1)}
const types={'.html':'text/html; charset=utf-8','.js':'text/javascript; charset=utf-8','.css':'text/css; charset=utf-8','.json':'application/json','.txt':'text/plain; charset=utf-8','.png':'image/png','.jpg':'image/jpeg','.jpeg':'image/jpeg','.svg':'image/svg+xml','.woff':'font/woff','.woff2':'font/woff2','.ico':'image/x-icon'};
createServer(async(req,res)=>{
if(!['GET','HEAD'].includes(req.method)){res.writeHead(405,{Allow:'GET, HEAD'});res.end();return}
try{
const pathname=decodeURIComponent(new URL(req.url,'http://localhost').pathname);
let file=resolve(root,`.${pathname}`);
if(file!==root&&!file.startsWith(root+sep)){res.writeHead(403);res.end();return}
let info=await stat(file).catch(()=>null);
if(info?.isDirectory()){file=resolve(file,'index.html');info=await stat(file).catch(()=>null)}
const status=info?.isFile()?200:404;
if(status===404){file=resolve(root,'404.html');info=await stat(file)}
res.writeHead(status,{'Content-Type':types[extname(file)]??'application/octet-stream','Content-Length':info.size});
if(req.method==='HEAD')res.end();else createReadStream(file).pipe(res);
}catch{res.writeHead(400);res.end('Bad request')}
}).listen(Number(process.env.PORT??3000),'127.0.0.1',()=>console.log(`Static site: http://localhost:${process.env.PORT??3000}`));