Feb 25

NodeJS Serving Static Files

We have previously generated dynamic hello world in NodeJS – let’s now try to do so via serving a static file instead.

The hello.html contains the following

<head><title>hello world</title></head>
<p>Hello world</p>

To serve this file we can quickly hack our handler to just load this file whenever we are pointing to root.

The fs module provides file I/O for NodeJS.  The simplest approach is probably to read the whole file into memory and write it out at once, via readFile:

var fs = require('fs');
fs.readFile('hello.html', function (err, data) {
    if (err) {
	res.writeHead(500, {'Content-Type':'text/plain'});
	res.end('internal error: ' + err);
    } else {
	res.writeHead(200, {'Content-Type':'text/html'});
	res.end(data, 'utf-8');

fs.readFile isn’t the most efficient method, especially for large files, but for now it suffices, and we’ll revisit how to handle large files in the future.

The above will serve hello.html with every request, since it’s embedded into the code. What we want is to be able to serve any file based on the incoming path.

For that – we’ll need the following

  • A mapping between the virtual path to physical path on disk
  • A content type map between the file extension to the content type

To map the physical path, we’ll need to start with a root path, say /tmp/node, and we’ll at this moment simply append the path to the root path.

function virtualToPhysical(path) {
    return '/tmp/node' + path; 
fs.readFile(virtualToPhysical(req.url), function (err, data) {

Since req.url always starts with /, the virtualToPhysical function will not have issue with missing / if used within the context of NodeJS.

The above change allows you to serve file from anywhere (assuming NodeJS has the proper permission) on the filesystem. However, we still need to deal with the mime types of different types of file.

Traditionally web servers such as Apache uses a mime.types file that holds the mapping between extensions and the content type. Although parsing mime.types isn’t all that difficult (just split on lines and split again on spaces, and then remove comments), it’s simpler to just use a pre-written module here, specifically node-mime.

Installing node-mime is simple, just issue the following command

$ npm install mime

Then add the following code

var mime = require('mime');
// on fileRead success
res.writeHead(200, {'Content-Type': mime.lookup(req.url) });

With the above – we can now serve arbitrary static files!



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

To use reCAPTCHA you must get an API key from https://www.google.com/recaptcha/admin/create