-
-
Save amejiarosario/53afae82e18db30dadc9bc39035778e5 to your computer and use it in GitHub Desktop.
const http = require('http'); | |
const url = require('url'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const port = process.argv[2] || 9000; | |
http.createServer(function (req, res) { | |
console.log(`${req.method} ${req.url}`); | |
// parse URL | |
const parsedUrl = url.parse(req.url); | |
// extract URL path | |
let pathname = `.${parsedUrl.pathname}`; | |
// based on the URL path, extract the file extention. e.g. .js, .doc, ... | |
const ext = path.parse(pathname).ext; | |
// maps file extention to MIME typere | |
const map = { | |
'.ico': 'image/x-icon', | |
'.html': 'text/html', | |
'.js': 'text/javascript', | |
'.json': 'application/json', | |
'.css': 'text/css', | |
'.png': 'image/png', | |
'.jpg': 'image/jpeg', | |
'.wav': 'audio/wav', | |
'.mp3': 'audio/mpeg', | |
'.svg': 'image/svg+xml', | |
'.pdf': 'application/pdf', | |
'.doc': 'application/msword' | |
}; | |
fs.exists(pathname, function (exist) { | |
if(!exist) { | |
// if the file is not found, return 404 | |
res.statusCode = 404; | |
res.end(`File ${pathname} not found!`); | |
return; | |
} | |
// if is a directory search for index file matching the extention | |
if (fs.statSync(pathname).isDirectory()) pathname += '/index' + ext; | |
// read file from file system | |
fs.readFile(pathname, function(err, data){ | |
if(err){ | |
res.statusCode = 500; | |
res.end(`Error getting the file: ${err}.`); | |
} else { | |
// if the file is found, set Content-type and send data | |
res.setHeader('Content-type', map[ext] || 'text/plain' ); | |
res.end(data); | |
} | |
}); | |
}); | |
}).listen(parseInt(port)); | |
console.log(`Server listening on port ${port}`); |
Line 36 potential reflected XSS vector (http://security.stackexchange.com/a/65242/2572). Do you intend to allow developers to use this code? If so, under what license? GPL, MIT/BSD, CC0, WTFPL? Stack overflow, from whence you linked this, uses the MIT license - is that what you intended?
Hey. I've been playing with this code, and I really really like it, but there is one change I think might be super important for security reasons.
If, at any point, a user converts the pathname to something more file readable (for instance, changing %20 to spaces), then a hack becomes possible.
If someone requests something like http://localhost:8528/%20./get_me.html
, the path name becomes ../get_me.html
, and they can get root access.
To fix this, you can make it so the max amount of periods at the start of a filename is 1
pathname = pathname.replace(/^(\.)+/, '.');
No built in 304?
python -mSimpleHTTPServer
Thanks for sharing your gist. I used your code and transformed it using ESM and async/await:
https://gist.github.com/stif/f063d2807556d18a786369425758cbc4
(Btw the "new URL (..)" constructor takes care of sanitize the URL from "../../etc/passwd" attacks, no need to use normalize/regex/whatever)
I wrote a post explaining this code: http://adrianmejia.com/blog/2016/08/24/Building-a-Node-js-static-file-server-files-over-HTTP-using-ES6/