Wednesday, 30 May 2018

Creating your first app with Node.js

Time to get down to business! Joking aside, we’re getting down to the nitty gritty of the subject now.
This is one of the most important chapters in the course because it introduces numerous Node.js concepts, most of which will be new to you. You will therefore need to read this chapter in a quiet place, gradually, and it may be a good idea to read through it again the following day to make sure that you’ve understood it correctly.
In this chapter we’re going to create a real Node.js app from start to finish.
You will find out what "low level" means and we will have to manage all parts of the web server that will handle the visitor’s HTTP requests and give them an HTML webpage.
This will be a chance for you to experiment with the infamous callbacks that I told you about in the first chapter, the functions that are run as soon as an event occurs. Node.js is full of them, so you won’t be able to avoid them! ;)

Web servers and threads

I think I’ve already said it numerous times, but I feel I should mention it again here: Node.js is low level. So low level that you will have to do things that you aren’t used to doing to make your program work properly.
When you create websites with PHP for example, you associate the language with an HTTP web server such as Apache or Nginx. Each of them has its own role in the process:
  • Apache manages HTTP requests to connect to the server. Its role is more or less to manage the in/out traffic.
  • PHP runs the .php file code and sends the result to Apache, which then sends it to the visitor.
As several visitors can request a page from the server at the same time, Apache is responsible for spreading them out and running different threads at the same time. Each thread uses a different processor on the server (or a processor core) (see next figure).
The Apache server is multithread
The Apache server is multithread
Node.js doesn’t use an HTTP server like Apache. In fact, it’s up to us to create the server! Isn’t that great? :D
Unlike Apache, Node.js is monothread. This means that there is only one process and one version of the program that can be used at any one time in its memory.
But I thought that Node.js was really fast because it could manage loads of requests simultaneously. If it’s monothread, can it only perform one action at a time?
Yes, it can only do one thing at a time and therefore only runs on one processor core. However, it does it efficiently, despite the latter, and is still much faster!
This is due to the event-orientated nature of Node.js. Apps that use Node never sit around doing nothing. As soon as there is an action that takes a little too long, the program hands over to Node.js, which will carry out other actions while waiting for the event to happen to tell it that the operation is finished (see next figure).
Node.js may be monothread, but it is flexible because of events
Node.js may be monothread, but it is flexible because of events

Constructing your HTTP server

I suggest we get to the heart of the matter with this first Node.js code:
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200);
res.end('Hi everybody!');
});
server.listen(8080);
In some ways it’s the "minimal code" for a Node.js project. Put it in a file and name it server.js (for example).
What does this code do?
It creates a mini web server which sends a "Hi everybody" message in every case, regardless of the page requested. This server is launched on the 8080 port on the last line.

Let’s analyze some code

Decomposing the code:
var http = require('http');
require makes a call to a Node.js library, here it’s the "http" library which allows us to create a web server. There are loads of libraries like this one, most of them can be downloaded using NPM, Node.js’s packet manager (we’ll learn how to use that later on).
The http variable represents the JavaScript object that will let us launch a web server and that’s exactly what we’re doing here:
var server = http.createServer();
We call the createSever() function contained within the http object and we save this server in the server variable. You’ll notice that the createServer function takes on a setting… and that this setting is a function. This is why the instruction is a little complicated, because it runs over multiple lines:
var server = http.createServer(function(req, res) {
res.writeHead(200);
res.end('Hi everybody!');
});
All this code corresponds to a call to the createServer(). Its settings contain the function to be run when a visitor connects to our website.
Note that you can do this in two steps, as mentioned previously. The function to be run is the callback function. We can define it beforehand in a variable and transmit this variable to createServer(). This way, the code is exactly the same as the previous one:
// Code exactly the same as the previous one
var instructionsNewVisitor = function(req, res) {
res.writeHead(200);
res.end('Hi everybody!');
}
var server = http.createServer(instructionsNewVisitor);
It’s very important that you understand this idea, because Node.js only works like that. There are callback functions everywhere and, generally speaking, they are placed within the lines of another function as you saw in my first code. This can seem a little tough to read, but you will soon get the hang of it, don’t worry. ;)
Don’t forget to close the callback function properly with a brace, to close the brackets that contain the function, and to place the infamous semicolon. This is why you see the }); symbols on the last line of my first code.
The callback function is therefore called each time a visitor connects to the website. It takes on 2 settings:
  • The visitor’s request (req in my examples): this object contains all the information about what the visitor asked for. In it you will find the name of the page that was requested, the settings, and any fields filled in on a form.
  • The response that you should send back (res in my examples): this is the object that you need to fill to give a response to the visitor. In the end, res will generally contain the HTML code of the page to be sent to the visitor.
Here, we are doing 2 simple things in the response:
res.writeHead(200);
res.end('Hi everybody!');
We send back the code 200 in the heading of the response, which tells the server "It’s OK everything’s fine" (we could, for example, have replied 404 if the requested page didn’t exist). You need to know that in addition to the HTML code, the server generally sends back a whole heap of other settings as a header. You need to know the HTML standards that show how clients and servers should communicate to be able to use it well. Here is another example of complexity caused by the fact that Node.js is low level. However, it helps us to understand all sorts of things. :)
Next, we end the response (with end()) by sending the message of our choice back to the browser. Here, we don’t even send HTML, just plain text.
Finally, the server is launched and "listens" to the 8080 port with the instruction:
server.listen(8080);

Testing the HTTP server

To test your first server, go into the console and type:
node server.js
The console doesn’t display anything and doesn’t respond – that’s totally normal. Now open your browser and go to the address http://localhost:8080. Connect your own machine to the 8080 port on which the Node.js program is running. You should get something that resembles the next figure.
Our first Node.js program is shown in the browser!
Our first Node.js program is shown in the browser!
To stop your Node.js server, return to the console and press ctrl + C to cut off the command.

Returning HTML code

Let’s sum up. We’ve created our first real app with our web server included. But the app is somewhat minimalist for the moment:
  • The message sent back is in plain text, it doesn’t even contain any HTML.
  • The application always sends back the same message, regardless of the page called (http://localhost:8080, http://localhost:8080/mypage, http://localhost:8080/file/otherpage).
For this chapter to be complete, we will need to cure these two problems. Let’s start here by seeing how to send some HTML back.
As I said before, there are rules that are to be respected between client and server. They communicate based on the HTTP standard invented by Sir Tim Berners-Lee. This standard is the foundation of the web (like HTML language, which was also invented by him ;) ).
What does the HTTP standard say? The server must indicate the type of data that it is about to send to the client because the server can return different types of data:
  • Plain text: text/plain
  • HTML: text/html.
  • CCS: text/ccs
  • A JPEG image: image/jpeg
  • An MPEG4 video: video/mp4
  • A ZIP file: application/zip
  • etc.
These are what we call the MIME types. They are sent in the header of the server’s response.
Do you remember how to write the response header with Node.js? We wrote this:
res.writeHead(200);
All we’ve done so far is enter the response code 200 to signify "OK, no errors". We need to add another setting that indicates the response’s MIME type. For HTML, it will therefore be:
res.writeHead(200, {"Content-Type": "text/html"});
Now that’s done, we can send HTML in the answer!
res.end('<p>Here is a paragraph of <strong>HTML</strong>!</p>');
Now our code looks like this:
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
res.end('<p>Here is a paragraph of <strong>HTML</strong>!</p>');
});
server.listen(8080);
Try out what you have learned by launching the application with the node  command in the console and opening your browser to http://localhost:8080 (see next figure):
An HTML paragraph returned by our Node.js app
An HTML paragraph returned by our Node.js app
Your paragraph of text is displayed and is formatted as planned! :)
But the HTML code isn’t valid, is it? We didn’t write a doctype or the <html> or <body> tags.
Yikes, you caught me red-handed! An invalid HTML code, I’m ashamed...
We can repair it. It’s easy, you simply need to send all the other tags that were missing.
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
res.write('<!DOCTYPE html>'+
'<html>'+
' <head>'+
' <meta charset="utf-8" />'+
' <title>My Node.js page!</title>'+
' </head>'+
' <body>'+
' <p>Here is a paragraph of <strong>HTML</strong>!</p>'+
' </body>'+
'</html>');
res.end();
});
server.listen(8080);
But you can’t write HTML like that, it’s awful!
We make do with what we have!
Don’t forget that Node.js is low level… :p
I assure you that no developer will create complex HTML web pages using it. There are ways of separating the HTML code from the JavaScript i.e. template systems. It’s not particularly relevant at the moment, given that we’re just getting used to the basics of Node.js. But if the subject interests you, there are plenty of Node.js modules dedicated to templates.

Determining which page is called and the settings

We know how to return HTML, but at the moment our app is returning the same thing every time. How do I create different pages with Node.js?
Try our little app on different URLs. Whichever page is called...
  • http://localhost:8080
  • http://localhost:8080/mypage
  • http://localhost:8080/folder/otherpage...
...the page displayed is always the same!
We need to know which page the visitor requested. Since we aren’t doing any tests at the moment our app always returns the same thing.
We’re going to find out how to recover:
  • The name of the page requested (/mypage, /page.html, /folder/otherpage, etc.)
  • The settings in the URL (eg: http://localhost:8080/mypage?lastname=doe&firstname=john).

Which page did the visitor request?

To find out which page the visitor requested, we’re going to use a new Node module called "url". We ask for its inclusion using:
var url = require("url");
Then, all we need to do is "parse" the visitor’s request like this to get the name of the page requested:
url.parse(req.url).pathname;
Here’s a simple code that will enable you to test this:
var http = require('http');
var url = require('url');
var server = http.createServer(function(req, res) {
var page = url.parse(req.url).pathname;
console.log(page);
res.writeHead(200, {"Content-Type": "text/plain"});
res.write('Well Hello');
res.end();
});
server.listen(8080);
First, run the script and launch your browser at the address http://localhost:8080. Then go back to the console. We’ll log the name of the requested page. This is what you should see:
/
/favicon.ico
I only loaded the home page, why am I seeing /favicon.ico?
Most browsers actually carry out a second query to retrieve the website icon (the "favicon" generally seen in the tabs). This is normal, don’t worry.
Now try to load "bogus pages" of your website to see what happens.
/testpage
/favicon.ico
/a/long/path/
/favicon.ico
/boguspage.html
/favicon.ico
If we ignore the favicon.ico, which is messing up the console, we can see that I tried to load the following pages:
  • http://localhost:8080/testpage
  • http://localhost:8080/a/long/path
  • http://localhost:8080/boguspage.html
So what? My website is still sending me back to same thing regardless of the page called!
True, but all you need to do is write a condition and the job’s done! ;)
var http = require('http');
var url = require('url');
var server = http.createServer(function(req, res) {
var page = url.parse(req.url).pathname;
console.log(page);
res.writeHead(200, {"Content-Type": "text/plain"});
if (page == '/') {
res.write('You\'re at the reception desk. How can I help you?');
}
else if (page == '/basement') {
res.write('You\'re in the wine cellar. These bottles are mine!');
}
else if (page == '/floor/1/bedroom') {
res.write('Hey, this is a private area!');
}
res.end();
});
server.listen(8080);
How about a little test to give you a bit of practice? Get an error message to display if the visitor requests an unknown page. And don’t forget to return a 404 error code!

What are the settings?

The settings are sent at the end of the URL, after the file pathway. Take this URL for example:
http://localhost:8080/page?fisrtname=John&lastname=Doe
The settings are contained in the ?firstname=John&lastname=Doe string. To retrieve this string, you simply need to use:
url.parse(req.url).query
The problem is that the whole string will be returned to you without first dividing the different settings. Thankfully, there is a Node.js module that takes care of it for us, i.e. querystring!
Include this module:
var querystring = require('querystring');
Then you can do:
var params = querystring.parse(url.parse(req.url).query);
You will then have a "params" settings table. To retrieve the firstname setting, just write: params['firstname'].
Let’s take a look at a full code that shows your first and last names (as long as these have been defined!):
var http = require('http');
var url = require('url');
var querystring = require('querystring');
var server = http.createServer(function(req, res) {
var params = querystring.parse(url.parse(req.url).query);
res.writeHead(200, {"Content-Type": "text/plain"});
if ('firstname' in params && 'lastname' in params) {
res.write('Your name is ' + params['firstname'] + ' ' + params['lastname']);
}
else {
res.write(''You do have a first name and a last name, don\'t you?');
}
res.end();
});
server.listen(8080);
Try going to http://localhost:8080?firstname=John&lastname=Doe to see the result and then change the first and last names to your own!

Summary diagram

Let’s sum up what we’ve just learnt in one single diagram (see next figure) before finishing.
Retrieving the URL and settings with Node.js
Retrieving the URL and settings with Node.js

Summing up 

  • With Node.js, your app must manage the web server (Apache equivalent) in addition to its own features. It should also determine the name of the page called and its settings so it knows what to return to the visitor.
  • Node.js libraries are called modules and they are loaded using require() .
  • With Node.js, we frequently send functions in settings of other functions. This determines which function should be called next when a task is finished.
  • Your app should usually return HTML to the visitor’s browser using the write()  method.
SOURCE

No comments:

Post a Comment