AllNode JS

Extending Our NodeJS static + Dynamic Server

Here, we would be extending / simplifying our server that we had made in our last post here.
Objectives –

  • We had a static URL handler which was invoked when URL pattern had /static/. It made the design very specific and not generic.
  • Need to make sure that in case there is no URL pattern handler for a given URL, a file for same name must be looked. If there is no such file, just raise 404 error.


Lets first update our server.js to handle only mappings.

var http = require('http'),
url = require('url');
function start(dispatch, handlers)
{
http.createServer(function(req, res) {
var _url = url.parse(req.url).pathname;
dispatch(handlers, _url, req, res);
}).listen(8888);
console.log("Server started !! ");
}
exports.start = start;

Does looks sweet with simple code. The dispatch method will now take care of all mappings as well as static file readings. Below is the code for dispatch as defined from our controller –

var staticHandler = require('./staticHandler');
function dispatch(handler, pathname, req, res) {
console.log("About to dispatch a request for " + pathname);
var content = "Hey "+pathname;
if (typeof handler[pathname] === 'function') {
content += handler[pathname](req);
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(content);
res.end();
} else {
console.log("No request handler found for " + pathname);
staticHandler.handleStatic(pathname, res);
}
}

What we have done here is just checked if there is a URL handler for a given pattern, in case we find it, we invoke it. Else we just pass the request to our static handler.
That’s it. Our server is now capable of handling any request. There is no pressure for you to put your static files in static directory on the server. Your middle ware server will take care of everything.
The updated code can be downloaded from this link.

5 thoughts on “Extending Our NodeJS static + Dynamic Server

  1. I truly wanted to send a quick message in order to appreciate you for all of the marvelous techniques you are giving out on this site. My rather long internet lookup has at the end been paid with sensible facts and strategies to talk about with my classmates and friends. I would suppose that many of us visitors are very fortunate to be in a fantastic website with very many brilliant people with very helpful tricks. I feel somewhat blessed to have used your website and look forward to some more awesome times reading here. Thank you once more for a lot of things.

  2. Hey – Thats a good read, though just a thought why wouldn’t you include Mime types while sending the response ?
    Thanks

  3. Hey Ravi,
    I am getting this
    Server started !!
    About to dispatch a request for /static/images/lion.jpg
    No request handler found for /static/images/lion.jpg
    About to read /static/images/lion.jpg
    File /var/www/node/static/static/images/lion.jpg
    About to read /static/images/lion.jpg
    About to dispatch a request for /static/images/
    No request handler found for /static/images/
    About to read /static/images/
    File /var/www/node/static/static/images/
    About to read /static/images/
    stream.js:81
    throw er; // Unhandled stream error in pipe.
    ^
    Error: EISDIR, read

  4. Hi Mayur –
    You would need to modify your staticFile Handler to handle directories as well.

    path.exists(filename, function(exists) {
    if(!exists) {
    console.log("not exists: " + filename);
    response.writeHead(404, {'Content-Type': 'text/html'});
    response.write('404 Not Found\n');
    response.end();
    return;
    }
    if(!fs.lstatSync(filename).isDirectory())
    {
    console.log("About to read "+pageUrl);
    var fileStream = fs.createReadStream(filename);
    response.writeHead(200);
    fileStream.pipe(response);
    }
    else
    {
    response.writeHead(302, {'location': 'index.html'});
    }
    response.end();

    I have currently used the lstatSync method which is synchronous as we would need to know if the path is directory before we proceed. You can also use lstat or stat which are Async methods.
    Also I have used response headers to forward such directory requests to index.html, you can choose any other options you like.
    PS: Do not forget to include response.end();
    -Supal

Leave a Reply

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