Skip to content

Instantly share code, notes, and snippets.

@GuilhermeRossato
Last active June 26, 2023 22:35
Show Gist options
  • Save GuilhermeRossato/ec540453a3dd0813aba2f4ada813c84b to your computer and use it in GitHub Desktop.
Save GuilhermeRossato/ec540453a3dd0813aba2f4ada813c84b to your computer and use it in GitHub Desktop.
Single file static http server with nodejs (without any dependency)
#!/usr/bin/node
const config = {host: '127.0.0.1', port: 8080, path: process.argv[2] || '.'};
const path = require('path');
const http = require('http');
const fs = require('fs');
const url = require('url');
const mimeLookup = {'aac':'audio/aac','abw':'application/x-abiword','arc':'application/x-freearc','avi':'video/x-msvideo','azw':'application/vnd.amazon.ebook','bin':'application/octet-stream','bmp':'image/bmp','bz':'application/x-bzip','bz2':'application/x-bzip2','csh':'application/x-csh','css':'text/css','csv':'text/csv','doc':'application/msword','docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document','eot':'application/vnd.ms-fontobject','epub':'application/epub+zip','gz':'application/gzip','gif':'image/gif','htm':'text/html','html':'text/html','ico':'image/vnd.microsoft.icon','ics':'text/calendar','jar':'application/java-archive','jpeg':'image/jpeg','jpg':'image/jpeg','js':'text/javascript','json':'application/json','jsonld':'application/ld+json','mid':'audio/midi','midi':'audio/midi','mjs':'text/javascript','mp3':'audio/mpeg','mpeg':'video/mpeg','mpkg':'application/vnd.apple.installer+xml','odp':'application/vnd.oasis.opendocument.presentation','ods':'application/vnd.oasis.opendocument.spreadsheet','odt':'application/vnd.oasis.opendocument.text','oga':'audio/ogg','ogv':'video/ogg','ogx':'application/ogg','opus':'audio/opus','otf':'font/otf','png':'image/png','pdf':'application/pdf','php':'application/x-httpd-php','ppt':'application/vnd.ms-powerpoint','pptx':'application/vnd.openxmlformats-officedocument.presentationml.presentation','rar':'application/vnd.rar','rtf':'application/rtf','sh':'application/x-sh','svg':'image/svg+xml','swf':'application/x-shockwave-flash','tar':'application/x-tar','tif':'image/tiff','tiff':'image/tiff','ts':'video/mp2t','ttf':'font/ttf','txt':'text/plain','vsd':'application/vnd.visio','wav':'audio/wav','weba':'audio/webm','webm':'video/webm','webp':'image/webp','woff':'font/woff','woff2':'font/woff2','xhtml':'application/xhtml+xml','xls':'application/vnd.ms-excel','xlsx':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','xml':'application/xml ','xul':'application/vnd.mozilla.xul+xml','zip':'application/zip','3gp':'video/3gpp','3g2':'video/3gpp2','7z':'application/x-7z-compressed'};
http.createServer(function (request, response) {
const uri = url.parse(request.url).pathname;
if (uri.includes("..") || uri.endsWith('/.env')) {
console.log(`${(new Date()).toISOString()} - 404 ${uri} (unsafe request blocked)`);
response.writeHead(404, {'Content-Type': 'text/plain'});
response.end();
return;
}
let filePath = path.resolve(config.path, decodeURIComponent(uri.substring(1)));
fs.stat(filePath, function (err, stats) {
if (err) {
if (err.code === "ENOENT") {
console.log(`${(new Date()).toISOString()} - 404 ${uri} Not found: "${filePath}"`);
response.writeHead(404, {'Content-Type': 'text/plain'});
response.write('404 Not Found\n');
} else {
console.log(`${(new Date()).toISOString()} - 500 ${uri} ${err.toString()}`);
response.writeHead(500, {'Content-Type': 'text/plain'});
response.write(err + '\n');
}
response.end();
return;
}
if (stats.isDirectory()) {
filePath += filePath[filePath.length - 1] === '/' ? 'index.html' : '/index.html';
}
fs.readFile(filePath, 'binary', function (err, file) {
if (err) {
if (err.code === "ENOENT") {
console.log(`${(new Date()).toISOString()} - 404 ${uri} Not found: "${filePath}"`);
response.writeHead(404, {'Content-Type': 'text/plain'});
response.write('404 Not Found\n');
} else {
console.log(`${(new Date()).toISOString()} - 500 ${uri} ${err.toString()}`);
response.writeHead(500, {'Content-Type': 'text/plain'});
response.write(`${err.message}\n`);
}
response.end();
return;
}
const type = mimeLookup[filePath.substring(filePath.lastIndexOf(".")+1)];
response.writeHead(200, {'Content-Type': type ? type : 'text/plain'});
response.write(file, 'binary');
response.end();
console.log(`${(new Date()).toISOString()} - 200 ${uri}`);
});
});
}).listen(config.port, config.host, () => console.log(`${(new Date()).toISOString()} - Serving "${config.path}" - Listening at http://${config.host}${config.port != 80 ? ":" + config.port : ""}/`));
const config={host:"127.0.0.1",port:8080,path:process.argv[2]||"."},i=require("path"),o=require("http"),e=require("fs"),a=require("url"),n={aac:"audio/aac",abw:"application/x-abiword",arc:"application/x-freearc",avi:"video/x-msvideo",azw:"application/vnd.amazon.ebook",bin:"application/octet-stream",bmp:"image/bmp",bz:"application/x-bzip",bz2:"application/x-bzip2",csh:"application/x-csh",css:"text/css",csv:"text/csv",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",eot:"application/vnd.ms-fontobject",epub:"application/epub+zip",gz:"application/gzip",gif:"image/gif",htm:"text/html",html:"text/html",ico:"image/vnd.microsoft.icon",ics:"text/calendar",jar:"application/java-archive",jpeg:"image/jpeg",jpg:"image/jpeg",js:"text/javascript",json:"application/json",jsonld:"application/ld+json",mid:"audio/midi",midi:"audio/midi",mjs:"text/javascript",mp3:"audio/mpeg",mpeg:"video/mpeg",mpkg:"application/vnd.apple.installer+xml",odp:"application/vnd.oasis.opendocument.presentation",ods:"application/vnd.oasis.opendocument.spreadsheet",odt:"application/vnd.oasis.opendocument.text",oga:"audio/ogg",ogv:"video/ogg",ogx:"application/ogg",opus:"audio/opus",otf:"font/otf",png:"image/png",pdf:"application/pdf",php:"application/x-httpd-php",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",rar:"application/vnd.rar",rtf:"application/rtf",sh:"application/x-sh",svg:"image/svg+xml",swf:"application/x-shockwave-flash",tar:"application/x-tar",tif:"image/tiff",tiff:"image/tiff",ts:"video/mp2t",ttf:"font/ttf",txt:"text/plain",vsd:"application/vnd.visio",wav:"audio/wav",weba:"audio/webm",webm:"video/webm",webp:"image/webp",woff:"font/woff",woff2:"font/woff2",xhtml:"application/xhtml+xml",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",xml:"application/xml ",xul:"application/vnd.mozilla.xul+xml",zip:"application/zip","3gp":"video/3gpp","3g2":"video/3gpp2","7z":"application/x-7z-compressed"};o.createServer((function(o,p){const l=a.parse(o.url).pathname;if(l.includes("..")||l.endsWith("/.env"))return console.log(`${(new Date).toISOString()} - 404 ${l} (unsafe request blocked)`),p.writeHead(404,{"Content-Type":"text/plain"}),void p.end();let c=i.resolve(config.path,decodeURIComponent(l.substring(1)));e.stat(c,(function(t,i){if(t)return"ENOENT"===t.code?(console.log(`${(new Date).toISOString()} - 404 ${l} Not found: "${c}"`),p.writeHead(404,{"Content-Type":"text/plain"}),p.write("404 Not Found\n")):(console.log(`${(new Date).toISOString()} - 500 ${l} ${t.toString()}`),p.writeHead(500,{"Content-Type":"text/plain"}),p.write(t+"\n")),void p.end();i.isDirectory()&&(c+="/"===c[c.length-1]?"index.html":"/index.html"),e.readFile(c,"binary",(function(t,i){if(t)return"ENOENT"===t.code?(console.log(`${(new Date).toISOString()} - 404 ${l} Not found: "${c}"`),p.writeHead(404,{"Content-Type":"text/plain"}),p.write("404 Not Found\n")):(console.log(`${(new Date).toISOString()} - 500 ${l} ${t.toString()}`),p.writeHead(500,{"Content-Type":"text/plain"}),p.write(`${t.message}\n`)),void p.end();const o=n[c.substring(c.lastIndexOf(".")+1)];p.writeHead(200,{"Content-Type":o||"text/plain"}),p.write(i,"binary"),p.end(),console.log(`${(new Date).toISOString()} - 200 ${l}`)}))}))})).listen(config.port,config.host,(()=>console.log(`${(new Date).toISOString()} - Serving "${config.path}" - Listening at http://${config.host}${80!=config.port?":"+config.port:""}/`)));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment