var fs = require("fs"); var pathlib = require("path"); var mimes = { txt: "text/plain", css: "text/css", html: "text/html", js: "application/javascript", json: "application/json", xml: "application/xml", zip: "application/zip", pdf: "application/pdf", gif: "image/gif", png: "image/png", jpeg: "image/jpeg", jpg: "image/jpeg", svg: "image/svg+xml", bmp: "image/bmp", webp: "image/webp", midi: "audio/midi", mp3: "audio/mpeg", ogg: "audio/ogg", webm: "video/webm", mkv: "video/mkv", ogv: "video/ogg", } function mimetype(path) { var unknown = "application/octet-stream"; var ext = pathlib.extname(path); if (ext) return mimes[ext.substr(1)] || unknown; else return unknown; } function sendfile(path, app, pathname, req, res) { fs.open(path, "r", (err, fd) => { if (err) { app.notice(err); res.writeHead(404); res.end(app.template(app.res404, { method: req.method, pathname: pathname })); return; } res.writeHead(200, { "Content-Type": mimetype(path) }); var rs = fs.createReadStream(null, { fd: fd }); rs.on("error", err => { app.warning(err); }); rs.on("data", d => res.write(d)); rs.on("end", () => res.end()); }); } module.exports = function(root, before) { return function(req, res, app) { var pn = req.urlobj.pathname; // Send a file function send(path) { sendfile(path, app, pn, req, res); } // Prevent leaking information if (pn.indexOf("../") !== -1 || pn.indexOf("/..") !== -1 || pn === "..") { res.writeHead(403); res.end(app.template(app.res403, { method: req.method, pathname: pn })); return; } // Join the web root with the request's path name var path = pathlib.join(root, pn.replace(before, "")); fs.stat(path, (err, stat) => { // If there's an error stat'ing, just error if (err) { app.notice(err); res.writeHead(404); res.end(app.template(app.res404, { method: req.method, pathname: pn })); return; } // If it's a directory, we want the index.html file, // or redirect to / if (stat.isDirectory()) { if (pn[pn.length - 1] !== "/") { res.writeHead(302, { location: pn + "/" }); res.end(); return; } path = pathlib.join(path, "index.html"); } // Send the file send(path); }); } }