Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Node.JS static file web server. Put it in your path to fire up servers in any directory, takes an optional port argument.
var http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs")
port = process.argv[2] || 8888;
http.createServer(function(request, response) {
var uri = url.parse(request.url).pathname
, filename = path.join(process.cwd(), uri);
path.exists(filename, function(exists) {
if(!exists) {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Found\n");
response.end();
return;
}
if (fs.statSync(filename).isDirectory()) filename += '/index.html';
fs.readFile(filename, "binary", function(err, file) {
if(err) {
response.writeHead(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
return;
}
response.writeHead(200);
response.write(file, "binary");
response.end();
});
});
}).listen(parseInt(port, 10));
console.log("Static file server running at\n => http://localhost:" + port + "/\nCTRL + C to shutdown");

Thank you!

agentgt commented Aug 31, 2011

likewise on the thank you!

Thank you for making this available

hhadri commented Jan 28, 2012

Thank you!

This doesn't set the mim type. You can use the mime module like this https://gist.github.com/1926868

shahalpk commented Mar 5, 2012

Thanks a lot!

thanks XD

Great stuff, exactly what I was looking for.

You may use the non-static module as well

Thanks for this! :)

Careful! This code is vulnerable to a directory traversal attack.

I'm just using it for a local web preview anyway

I'm just getting started with node.js and backbone.js and this has been perfect for setting up demo apps quickly.

I needed to put up a holding page for a website I was building and this was an awesome lightweight solution... Thanks!

jagtesh commented Jan 8, 2013

Just what I was looking for. Danke Shoen!

Consider also python -m SimpleHTTPServer 888 or twistd -n web -p 8888 --path .. The former is installed pretty much anywhere where there's Python, the latter is better performing and is bundled with many distributions including Mac OSX - no need for pasting/downloading another file.

yosske commented Jan 21, 2013

Thanks!

So good !

Premier commented Feb 24, 2013

Great!

Thank you, this rocks!

Thanks!

path.exists should be changed to fs.exists

Nice! I typically use

python -m SimpleHTTPServer

to serve the cwd.

srgg6701 commented Dec 5, 2013

Brilliant solution!

samof76 commented Feb 4, 2014

fantastic.... love this!

nice, this totally is the javascript spirit of the python SimpleHTTPServer

I dumped in piping because I was using it to transfer larger files. May be slow... gist

Great example to understand

Wow the first one that works for me thank very much for this code!
Well, it works everywhere except in...surprise: IE11 & <

Ajedi32 commented Apr 21, 2014

Quick question: does this script ensure that data in higher-level directories is inaccessible via http requests? E.g. I can't request /../../../../.ssh/id_rsa (just an example) and have it send that data to me?

@dylantack @Ajedi32 I was concerned about this as well, but after some quick testing it appears that url.parse is sanitizing the requested path. For example, if this node server is running from /home and you try visiting 1.2.3.4:8888/../../../../.ssh/id_rsa it resolves to /home/.ssh/id_rsa.

Thanks.

Great work, Thanks

FYI, if you're serving media files you might want to look at the send module. It will handle large files better, and Partial Content requests (important for HTML5 video).

https://github.com/visionmedia/send

To be sure to avoid transversal directory attacks without relying on url.parse, one could also do

var cwd = process.cwd();
http.createServer (function (req, res) {
    var uri = url.parse(req.url).pathname,
        filename = path.join(cwd, uri);
    if (filename.indexOf(cwd) !== 0)
        // Abort
}

Also, I would use filename = path.join(filename, 'index.html') instead of filename += '/index.html'. / isn't necessarily the OS separator, or we wouldn't use a path module.

johnjqc commented Jan 7, 2015

muy bueno, gracias

thanks a lot dude

Many thanks.

Shouldn't the method "exists" be used with fs instead of path?
On line 12 of the code we have:

path.exists(filename, function(exists) {...});

This gave me an error and it seemed fine after I replaced it with:

fs.exists(filename, function(exists) {...});

einsiol commented Jun 7, 2015

Agree with the last comment, replacing path.exist with fs.exist fixed an error that I did not fully understand. Otherwise, fantastic solution, perfect for beginners :)

raidenz commented Jun 23, 2015

yes thanks brandt1871 path.exists is now called fs.exists

fordnox commented Jul 17, 2015

Same issue here, path.exists is now called fs.exists

Please fix for future generations :)

Thanks!!!

Deele commented Sep 28, 2015

Please, include package.json so that we could npm install. Thanks!

You saved my day brotha.. Thanks :) ~

For those newbies out there, path.exists has been depricated to fs.exists.

thank u

If anyone is interested in ES6+ version, I've revamped it here.

kostasx commented May 23, 2016

Small typo: fs = require("fs") is missing a comma at the end of the line, making port on the next line a global variable.
Thank you for sharing!

archasek commented Jun 9, 2016

Fixed the whole code. Enjoy :)

var http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs"),
    port = process.argv[2] || 8888;

http.createServer(function(request, response) {

  var uri = url.parse(request.url).pathname
    , filename = path.join(process.cwd(), uri);

  fs.exists(filename, function(exists) {
    if(!exists) {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.write("404 Not Found\n");
      response.end();
      return;
    }

    if (fs.statSync(filename).isDirectory()) filename += '/index.html';

    fs.readFile(filename, "binary", function(err, file) {
      if(err) {        
        response.writeHead(500, {"Content-Type": "text/plain"});
        response.write(err + "\n");
        response.end();
        return;
      }

      response.writeHead(200);
      response.write(file, "binary");
      response.end();
    });
  });
}).listen(parseInt(port, 10));

console.log("Static file server running at\n  => http://localhost:" + port + "/\nCTRL + C to shutdown");

CforED commented Jul 4, 2016

Hi, Everyone:

Problem: There is a failure in the JavaScript code (server.js) to route a var to the following directory: ./public/index.html.

Symptoms: HTTP Error 403.14 - Forbidden.

Request for Support: What is the correct JavaScript to route var to a particular directory?

URL References:

1.) GitHub URL link: https://github.com/CforED/WebSite/blob/master/server.js

2.) Gist URL link: https://gist.github.com/CforED/177a2e73dfb87313576376fc00a2c9f4.js

3.) GitHub URL link to website:
https://github.com/CforED/WebSite/tree/master/public

Hal

I created a new one that handles MIME types and uses ES6+

https://gist.github.com/amejiarosario/53afae82e18db30dadc9bc39035778e5

Got an error with path.exists, changed it to fs.exists and the snippet worked fine.

duluca commented Feb 28, 2017

@kovid-rathee I ran in to the same issue and your solution worked!

Hey, guys what do you think about this article?
he best Node.js framework for your project: Express.js, Koa.js or Sails.js is express js the best framework for Node js?

Awesome! I am new to Node.js and was trying to figure out how to configure this...This worked with a minor update as givne in another post creationix/howtonode.org#88
Thank you very much!

robole commented Jun 26, 2017

ty. min req, what i was after

dkebler commented Oct 31, 2017

path.exists has been deprecated. If you want a sync check then

  if (!fs.statSync(filename)) {
    response.writeHead(404, {'Content-Type': 'text/plain'})
    response.write('404 Not Found\n')
    response.end()
    return
  }

dkebler commented Oct 31, 2017

even better how about the handler's fs stuff all async with callbacks

fs.stat(filename, function(err,stats) {
    if (err) {
      response.writeHead(404, {'Content-Type': 'text/plain'})
      response.write('404 Not Found\n')
      response.end()
      return
    }

    if (stats.isDirectory()) filename += '/index.html'

    fs.readFile(filename, 'binary', function(err, file) {
      if(err) {
        response.writeHead(500, {'Content-Type': 'text/plain'})
        response.write(err + '\n')
        response.end()
        return
      }
      response.writeHead(200)
      response.write(file, 'binary')
      response.end()
    })
  })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment