If you wanna know about someone , listen ,deal and observe , only you can say who I am

Future of Web-development :NodeJs Tutorial part 4 Useful request handlers

So far we successfully laid out the modules that we need for our application , and connected them together , Right now, we need to be able to make the request handles be able to send back something to the user ( reply ) , if you come from a PHP / python background you might want to prepare the content and return it up the layes till the server sends it back to the user , but then you are blocking all operations till the result return , and since the javascript doest generate a thread for every request , all the other users request will experience delay till the slow request returns .

so instead of sending the result generated by content handler to the server , we want to send the server to the request handler, ie. passing a reference from the response object to the request handler . and the request handler can use that reference to serve the content it needs to the user .

so here is how our modifications should reflect on our file :

first the server.js

var http = require("http");
var url = require("url");
function start(route, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(handle, pathname, response);
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;

router.js

function route(handle, pathname, response) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](response);
} else {
console.log("No request handler found for " + pathname);
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not found");
response.end();
}
}
exports.route = route;

Last the requestHandles.js

var exec = require("child_process").exec;
function start(response) {
console.log("Request handler 'start' was called.");
exec("ls -lah", function (error, stdout, stderr) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(stdout);
response.end();
});
Building the application stack 47
}
function upload(response) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello Upload");
response.end();
}
exports.start = start;
exports.upload = upload;

Now our application can respond to requests without blocking and depending on each other .

Serving Something useful

now we connected the parts of our application together and we are ready to serve content to the user, we will discuss a simple example of handling post request ..

Handling POST requests

We will present a textarea that can be filled by the user and submitted to the server in a POST request. Upon receiving and handling this request, we will display the content of the textarea.

The HTML for this textarea form needs to be served by our /start request handler, so let’s add it right away, in file re-questHandlers.js

function start(response) {
console.log("Request handler 'start' was called.");
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" content="text/html; '+
'charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" method="post">'+
'<textarea name="text" rows="20" cols="60"></textarea>'+
'<input type="submit" value="Submit text" />'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {"Content-Type": "text/html"});
response.write(body);
response.end();
}
Building the application stack 51
function upload(response) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello Upload");
response.end();
}
exports.start = start;
exports.upload = upload;

I can guess that you are thinking that including view inside controller is ugly , but i didnt want to include that in this crash course and you can easily find how to do this abstraction using a simple search 🙂

lets rather now discuss how we are going to serve the post request in a non blocking way  Which makes sense, because POST requests can potentially be very large

To make the whole process non-blocking, Node.js serves our code the POST data in small chunks, callbacks that are called upon certain events. These events are data (an new chunk of POST data arrives) and end (all chunks have been received).

We need to tell Node.js which functions to call back to when these events occur. This is done by adding listeners to the request object that is passed to our onRequest callback whenever an HTTP request is received. This basically looks like this:

now where to put this logic , i decided to put it in the server logic because it is up to the server to prepare the data of the request and send it along to the request handler .

lets start with server.js

var http = require("http");var url = require("url");function start(route, handle){function onRequest(request, response){var postData ="";var pathname = url.parse(request.url).pathname;
console.log("Request for "+ pathname +" received.");
request.setEncoding("utf8");
request.addListener("data",function(postDataChunk){
postData += postDataChunk;
console.log("Received POST data chunk '"+
postDataChunk +"'.");});
request.addListener("end",function(){
route(handle, pathname, response, postData);});}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");}
exports.start = start;

Let’s add even more awesome to our app. On the /upload page, we will display the received content. To make this possible, we need to pass the postData on to the request handlers, in router.js:

function route(handle, pathname, response, postData) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](response, postData);
} else {
console.log("No request handler found for " + pathname);
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not found");
response.end();
}
}
exports.route = route;

And in requestHandlers.js, we include the data in our response of the upload request handler

function start(response, postData){
console.log("Request handler 'start' was called.");var body ='<html>'+'<head>'+'<meta http-equiv="Content-Type" content="text/html; '+'charset=UTF-8" />'+'</head>'+'<body>'+'<form action="/upload" method="post">'+'<textarea name="text" rows="20" cols="60"></textarea>'+'<input type="submit" value="Submit text" />'+'</form>'+'</body>'+
Building the application stack 56'</html>';
response.writeHead(200,{"Content-Type":"text/html"});
response.write(body);
response.end();}function upload(response, postData){
console.log("Request handler 'upload' was called.");
response.writeHead(200,{"Content-Type":"text/plain"});
response.write("You've sent: "+ postData);
response.end();}
exports.start = start;
exports.upload = upload;

One last thing for this topic: what we pass on to the router and the request handlers is the complete body of our POST request. We will probably want to consume the individual fields that make up the POST data, in this case, the value of the text field. We already read about the querystring module, which assists us with this:


 

var querystring = require("querystring");
function start(response, postData) {
console.log("Request handler 'start' was called.");
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" content="text/html; '+
'charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" method="post">'+
'<textarea name="text" rows="20" cols="60"></textarea>'+
'<input type="submit" value="Submit text" />'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {"Content-Type": "text/html"});
response.write(body);
response.end();
}
function upload(response, postData) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("You've sent the text: "+
querystring.parse(postData).text);
response.end();
}
Building the application stack 58
exports.start = start;
exports.upload = upload;

Well , You can now test your application , and i guess having that running , means that you are ready to go out there in the wild world and start learning and mastering NodeJs on your own , the community is getting bigger by the day and you wont find  difficulty finding more tutorials and material , this tutorial itself was taken from ” The Node Beginner Handboo”

More Sources to learn NodeJS

 

The official website and documentation

http://www.nodejs.org/

 

The NodeCloud directory  (contains a mega collection of sites related to Node JS )

http://www.nodecloud.org/

 

The NodeJs  community wiki

https://github.com/joyent/node/wiki

 

 

 

Leave a comment