Creating our own Modules

Modules are the basic building blocks of Node.js applications. With all our changes, our file is becoming a bit clumsy; moreover, we are putting our infrastructure (server and router) with the application logic (the handlers) in the same place. As mentioned earlier, Node.js builds on the CommonJS module system. In Node.js, a module and a file have a one-to-one relation. Let us move the server and router to their own modules. Save the following in a file called server.js:

var http = require("http");
var url = require("url");

function onRequest(request, response) {
  var pathname = url.parse(request.url).pathname;
  console.log("Request for " + request.method + pathname +" received.");
  if(typeof(routes[request.method + pathname])==='function'){
    routes[request.method + pathname](request, response);
  }
  else{
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.end("404 Not Found");
  }
}

var routes = {};

exports.forRoute = function(method, path, handler){
  routes[method + path] = handler;
};

exports.start = function(){
  http.createServer(onRequest).listen(9999);
  console.log("Server has started.");
};

Most of the logical aspects of the code remain the same, but we have made some very subtle structural changes. The first one is that we have taken the routes out of the route object. Any variables declared in the file are available within the module and are not accessible from outside the module.

  if(typeof(routes[request.method + pathname])==='function'){
    routes[request.method + pathname](request, response);
  }

As the route object is gone, we can now directly access the routes within the module and not through the route object.

The other and more obvious change is exports. Since nothing from within the module is available outside the module, we have to add the methods/objects that we want to expose to the implicit exports object. Ideally, you should expose only those methods relevant to the end user of your module.

exports.forRoute = function(method, path, handler){
  routes[method + path] = handler;
};

exports.start = function(){
  http.createServer(onRequest).listen(9999);
  console.log("Server has started.");
}

We are exposing two methods from our module: the forRoute method (originally, the on method in the route object), and the start method that wraps the code to start the HTTP server. We also move the application logic to its own module called app.js, which is shown in the following code snippet:

var server = require("./server.js");
server.forRoute("GET", "/start", function(request, response){
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello");
  response.end();
});

server.forRoute("GET", "/finish", function(request, response){
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Goodbye");
  response.end();
});

server.forRoute("POST", "/echo", function(request, response){
  
  var incoming = "";

  request.on('data', function(chunk) {
    incoming += chunk.toString();
  });

  request.on('end', function(){
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write(incoming);
    response.end();
  });
});

server.forRoute("GET", "/echo", function(request, response){
  var body = '<html>' + 
  '<head><title>Node.js Echo</title></head>' + 
  '<body>' + 
  '<form method="POST">' + 
  '<input type="text" name="msg"/>' + 
  '<input type="submit" value="echo"/>' + 
  '</form>' + 
  '</body></html>';

  response.writeHead(200, {"Content-Type": "text/html"});
  response.write(body);
  response.end();
});

server.start();

Again, the logical aspects remain unchanged; the changes are only in the structure.

var server = require("./server.js");

The previous line, which is also the first line in the previous code snippet, shows us how our server module is loaded. This is similar to loading core modules like HTTP or URL, but here we are loading the module and passing its filename. The object created by this require method, the server object, will have two methods that will be exposed: forRoute and start.

Next, we replace all the calls to route.on with the server.forRoute method. . And finally, we call the server.start method to start the HTTP server.

server.start();
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset