Node.js: Express tutorial
This article is part of our Academy Course titled Building web apps with Node.js.
In this course, you will get introduced to Node.js. You will learn how to install, configure and run the server and how to load various modules.
Additionally, you will build a sample application from scratch and also get your hands dirty with Node.js command line programming.
Check it out here!
Table Of Contents
2. Express.js Installation3. Express.js Objects
7. Sample web application with NeDB
- 7.1. Installation
- 7.2. Configuration Code
- 7.3. Router Handling Code
- 7.4. Angular.js part
- 7.5. Angular Template and HTML
1. Introduction
Express.js is a powerful web development framework for the Node.js (Node) platform. Express.js comes with the rest of the Node.js middleware modules. These modules are JavaScript components which can be used in Node.js based web applications to make the application layered and more modular.
With express.js, except for the express.js APIs, other node.js core APIs can also be called. The Express.js framework can be used in order to develop any kind of web application, from simple to complex ones. As always, when developing with Node.js , we have to keep in mind the asynchronous behaviour of our application.
2. Express.js Installation
After installing Node.js in our machine, it is easy to also install express.js. This is accomplished via the node.js package manager. We need to install express.js as a node module with the -g option as an npm install command at terminal.
The command to install Express is the following:
$ sudo npm install express -g
This will install the latest stable version of Express.
If we need to install express.js locally, then we need to run the following:
$ sudo npm install express
The difference between local and global installation is this: for local installation, the express.js will be available in the node_modules
folder within the express.js folder, while for the global installation, the express.js will be available at the node executable path for all the applications which are developed on the particular machine.
The express.js installation can be confirmed by requesting the version for express.js. Run the following in the terminal:
$ express –V > 3.4.7
3. Express.js Objects
3.1. The application object
The application object is an instance of Express, generally presented by the variable named ‘app’. This is the main object of our Express applocation and all functionality is built on top of that object.
Creating an instance of the Express.js module within the node application is done as follows:
var express = require('express'); var app = new express();
3.2. The request object
Now, when a web client makes a request to the Express application, the HTTP request object is created. Inside all the application callbacks, whenever the request objects are passed as reference, those are represented with the conventional variable req
. This request object holds all the HTTP stack related variables, such as headers information, HTTP methods and related properties for that particular request from the web client.
Let’s see the most important methods of Request object:
- req.params: Holds the values of all the parameters of the request object.
- req.params(name): Returns value of a specific parameter from the Web URL GET params or POST params.
- req.query: Takes values from a GET method submission.
- req.body: Takes values from a POST form submission.
- req.get(header): Gets the request HTTP header.
- req.path: The request path.
- req.url: The request path with query parameters.
3.3. The response object
The response object is created along with the request object, and is generally represented by a variable named res
. In the HTTP Request-Response model, all the express middlewares work on the request and the response objects while one is passing the control after another.
Let’s see the most important methods of Response object:
- res.status(code): The HTTP response code.
- res.attachment([filename]): The response HTTP header Content-Disposition to attachment.
- res.sendfile(path, [options], Sends a file to the client [callback]).
- res.download(path, [filename], Prompts the client to download from [callback]).
- res.render(view, [locals], Renders a view callback).
4. Concepts used in Express
4.1. Asynchronous JavaScript
Node.js programming is mainly based on Asynchronous Javascript Programming. All of the modules in node.js are built asynchronous in nature. So, the execution of the code from one layer to another generally is performed within callback functions.
As node.js program executes in an event loop, the end user generally does not face any “blocking” from the view layer, i.e. the web browser or mobile browser etc. Generally the callback function is passed as an async function to be executed. This function will return the result to the upper function when the execution of code is completed.
Note that all the programs within express.js and the associated programs are installed in the node.js environment as node modules. For any node.js application, the deployment configuration is written in a “package.json” file. If we need to install the application as a node module in the node.js environment, i.e. through the npm install command, we should also include the package.json file.
4.2. Middlewares in node.js applications
A middleware in a node.js application context is a JavaScript function which will handle HTTP requests. It will be able to handle the request and the response objects from HTTP request, perform some operation on the request, send back the response to the client and finally pass the objects/results to the next middleware. Middlewares are loaded in an Express application with the app.use() method.
A basic example of a middleware is oe that will handle a GET request method, as follows:
app.use(function(req, res, next) { console.log('Request Query : ' + req.query); next(); });
This will print the “querystring” within the request object.
The majority of the Express.js functionality is implemented with its built-in middlewares. One of the Express.js middleware is the router middleware, which is responsible for routing the HTTP requests inside Express applications to the appropriate data handler functions. From a user perspective, it is the navigational functionality in a web application.
The destinations of the HTTP request URIs are defined via routes in the application. Routes are the controlling points for the response from a request, i.e they decide where to dispatch a specific request by analysing data carried on the request object. In traditional web applications, like a JEE Application, this functionality is handled by the Controller in the application. Route handlers may be defined in the app.js file or loaded as Node modules.
Defining the routes and their handlers in the app.js file works fine when the number of routes is relatively small.
The following code presents an example of routes.js in the Node module:
module.exports = function(app) { app.get('/', function(req, res) { // Send a plain text response res.send('First Express Application!'); }); app.get('/hello.text', function(req, res) { // Send a plain text response res.send('Hello!'); }); app.get('/contact', function(req, res) { // Render a view named contact res.render('contact'); }); };
The app.js file can be defined as below:
var http = require('http'); var express = require('express'); var app = express(); var routes = require('./routes')(app); http.createServer(app).listen(3000, function(){ console.log('Express server listening on port ' + 3000); });
A request handler can send a response back to the client using response methods in the response object.
5. Definition of Routes
Generally, a URL (Uniform Resource Locator) combines the HTTP request method (GET or POST) and the path pattern for a web application. The routes handle the URL with the appropiate route handler, which executes the job for any particular action for that URL. A request to the server that matches a route definition is routed to the associated route handler. The route handlers are also able to send the HTTP response or pass the request to the next middleware, if necessary.
Routes in Express are defined using methods named as the HTTP methods, for example app.get(), app.post(), app.put() and so on.
There is also another set of string-based route identifiers, which are used in order to specify placeholders for the request path.
The following example demonstrates this concept:
app.get('/user/:id', function(req, res) { res.send('user id: ' + req.params.id); }); app.get('/country/:country/state/:state/city/:city', function(req, res) { res.send(req.params.country + ', ' + req.params.state + ', ' + req.params.city); }
So, the value of the placeholder name will be available in the req.params object which we can access as in the above example.
Below is a code snippet for an optional parameter:
app.get('/feed/:datatype?', function(req, res) { if (req.params.datatype) { res.send('Data Type: ' + req.params.datatype); } else { res.send('Text Data'); } });
5.1. How to handle routes in express.js
When a request is made to the server, for the given route definition, the associated callback function will be executed in order to process the request and send back the response. These callback functions generally define the behaviour of our application.
5.2. Namespaced Routing
We can define the routes on the basis of a namespace, which will act as the root path and then the rest of the routes will be defined relatively to that route. By default, express.js does not have the capability for namespaced routing. For getting the advantage of this functionality, we will have to install the ‘express-namespace’ node module.
The command for the installation is the following:
$ npm install express-namespace
So now we can write the app.js as follows:
var http = require('http'); var express = require('express'); // express-namespace should be loaded before app is instantiated var namespace = require('express-namespace'); var app = express(); app.use(app.router); app.namespace('/posts', function() { app.get('/', function(req, res) { res.send('all posts'); }); app.get('/new', function(req, res) { res.send('new post'); }); app.get('/edit/:id', function(req, res) { res.send('edit post ' + req.params.id); }); app.get('/delete/:id', function(req, res) { res.send('delete post ' + req.params.id); }); app.get('/2013', function(req, res) { res.send('articles from 2014'); }); // Namespaces can be nested app.namespace('/2014/jan', function() { app.get('/', function(req, res) { res.send('posts from jan 2014'); }); app.get('/angularjs', function(req, res) { res.send('articles about Angular.js from jan 2014'); }); }); }); http.createServer(app).listen(3000, function() { console.log('App started'); });
We can see the results for the following urls:
http://localhost:3000/posts/ http://localhost:3000/posts/edit/1 http://localhost:3000/posts/delete/1 http://localhost:3000/posts/2014 http://localhost:3000/posts/2014/jan http://localhost:3000/posts/2014/jan/angularjs
6. HTTP response in Express
A response from express.js can be generated with a minimal route and a callback as below:
app.get('/', function(req, res) { res.send('our application response'); });
Express.js can handle any type of Error in Application which are standard HTTP response error codes.
6.1. Setting the HTTP status code
We can set the HTTP status code by passing the number to the res.status() method.
An example for sending the 404 Status code can be found below:
app.get('/', function(req, res) { // Set the status res.status(404); // Specify the body res.send('404 Error'); });
By default, express.js sends response code 200.
Also we can send the status as a chained response:
app.get('/', function(req, res) { // Status and body in one line res.status(404).send('resource not found'); });
Some HTTP methods, like res.send(), res.json(), and res.jsonp() are capable of sending the HTTP status code themselves.
In case of sending a 200 status code:
The example is for res.send():
app.get('/', function(req, res) { res.send('welcome'); });
Now if a number is passed in the body, it will be like:
app.get('/', function(req, res) { res.send(404); });
or
app.get('/', function(req, res) { res.send(404, 'not found'); });
6.2. Setting HTTP headers
Express provides an interface for setting HTTP headers in the response message. We have to pass two parameters to the res.set() method; the first parameter is the header name and the second parameter is the value of the parameter.
An example for setting the standard HTTP header with custom header variables is the following:
app.get('/', function(req, res) { res.status(200); res.set('Content-Type', 'text/plain; charset=us-ascii'); res.set('X-Custom-Message', 'it is a custom message'); res.send('HTTP header setting example'); });
6.3. Sending data
If we want to serve plain text with the response, we can write:
app.get('/', function(req, res) { res.send('</pre> <h1>Plain text</h1> <pre> '); });
It will show <h1>Plain text</h1>
in browser.
Equivalent to this will be:
app.get('/', function(req, res) { res.set('Content-Type', 'text/plain'); res.send('</pre> <h1>Plain text</h1> <pre> '); });
If we want to see the HTML Equivalent of this, then we should try:
app.get('/', function(req, res) { res.set('Content-Type', 'text/html'); res.send('</pre> <h1>Plain text</h1> <pre> '); });
If we want json as output, we can do this by setting the json object in response i.e. by using the res.json method.
app.get('/', function(req, res) { res.json({message: 'This is example of json'}); });
It will set a default 200 HTTP Status with the response.
For responding with content negotiation, the response object will return like the following with res.format method:
app.get('/', function(req, res) { res.format({ 'text/plain': function() { res.send('Plain text'); }, 'text/html': function() { res.send('<b>welcome</b>'); }, 'application/json': function() { res.json({ message: 'welcome' }); }, 'default': function() { res.send(406, 'Not Acceptable'); } }); });
The server will respond based on the data type mentioned in the HTTP Accept header.
Now we will try to make a complete node.js application where the GET and POST methods are used from Express.js and will see how all these are tied together.
7. Sample web application with NeDB
We have chosen nedb for our datastore to make the application simple for reader. NeDB is a javascript based Embedded database. According to this, NeDB is an
“Embedded persistent database for Node.js, written in Javascript, with no dependency (except npm modules of course).”
To make the application, we have selected:
- Angular.js for client side development – Single Page Application.
- Cross Domain Communication in between Angular.js and Node.js.
- Node.js for server side development.
- Rest based web service creation with express.js.
- Database – NeDb.
- Node.js NeDB Module Extention.
We have created a Proof of Concept with a Javascript based web server, where we utilized NeDB with the javascript based framework Node.js and angular.js on the client side.
The architecture at a glance:
Here are the steps:
7.1. Installation
- Download and install Node.js as described here.
- To Develop the application we need to install nedb module for Node.js.
npm install nedb
- We need to install express.js for node.js.
npm install express
7.2. Configuration Code
Now, we will try to describe the used code portion:
var application_root = __dirname, express = require("express"), path = require("path");
Here we have initialised the express.js based on the Node.js concepts discussed above.
var app = express();
Here we have initialised the express web server and reference the app variable.
var databaseUrl = "/home/sampleuser/nedb/user.db"; var Datastore = require('nedb'); db = {}; db.users = new Datastore({ filename: databaseUrl, autoload: true }); // to autoload datastore
Here we have made the connection to the nedb database using the Node.js nedb module extension library.
// Config app.configure(function () { app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(application_root, "public"))); app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); });
Here we have made the configuration related to express.js.
7.3. Router Handling Code
app.get('/api', function (req, res) { res.send('Our Sample API is up...'); });
Here we have made our first REST based web service and tested whether the express.js is up.
Our sample api will be: http://127.0.0.1:1212/api (GET Method).
app.get('/getangularusers', function (req, res) { res.header("Access-Control-Allow-Origin", "http://localhost"); res.header("Access-Control-Allow-Methods", "GET, POST"); // The above 2 lines are required for Cross Domain Communication(Allowing the methods that will come as Cross Domain Request // More on this in later part of the code db.users.find('', function(err, users) { // Query in NeDB via NeDB Module if( err || !users) console.log("No users found"); else { res.writeHead(200, {'Content-Type': 'application/json'}); // Sending data via json str='['; users.forEach( function(user) { str = str + '{ "name" : "' + user.username + '"},' +'\\n'; }); str = str.trim(); str = str.substring(0,str.length-1); str = str + ']'; res.end( str); // Prepared the jSon Array here } }); });
Here we have created another REST API to get all usernames from a user collection and so we have performed the necessary NeDB query.
Our sample api will be: http://127.0.0.1:1212/getangularusers (GET Method).
app.post('/insertangularneuser', function (req, res){ console.log("POST: "); res.header("Access-Control-Allow-Origin", "http://localhost"); res.header("Access-Control-Allow-Methods", "GET, POST"); // The above 2 lines are required for Cross Domain Communication(Allowing the methods that come as Cross // Domain Request console.log(req.body); console.log(req.body.mydata); var jsonData = JSON.parse(req.body.mydata); db.users.save({email: jsonData.email, password: jsonData.password, username: jsonData.username}, function(err, saved) { // Query in NeDB via NeDB Module if( err || !saved ) res.end( "User not saved"); else res.end( "User saved"); }); });
Here we have made a POST request to create a user via a REST invocation.
Our sample api will be: http://127.0.0.1:1212/insertangularneuser (Post Method).
// Launch server app.listen(1212);
We have made the server to listen at 1212 port.
Now we can run node appnedbangular.js from command prompt/terminal.
7.4. Angular.js part
We have used Angular.js for our client side work and development. We have made the choice of Angular.js as our front-end development tool as this maintains a clear client-side Model-View-Presenter Architecture and makes the code more structured.
Since this part of the tutorial mainly concentrates on node.js and express.js, the reader is urged to acquire more knowledge about Angular.js here.
We provide inline doucmentation with our code to help you better understand the application with Angular.js
So, below is the code for the Angular Controller
.
'use strict'; var myApp = angular.module('myApp', []); // Taking Angular Application in Javascript Variable // Below is the code to allow cross domain request from web server through angular.js myApp.config(['$httpProvider', function($httpProvider) { $httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers.common['X-Requested-With']; } ]); /* Controllers */ function UserListCtrl($scope, $http, $templateCache) { var method = 'POST'; var inserturl = 'http://localhost:1212/insertangularneuser';// URL where the Node.js server is running $scope.codeStatus = ""; $scope.save = function() { // Preparing the Json Data from the Angular Model to send in the Server. var formData = { 'username' : this.username, 'password' : this.password, 'email' : this.email }; this.username = ''; this.password = ''; this.email = ''; var jdata = 'mydata='+JSON.stringify(formData); // The data is to be string. $http({ // Accessing the Angular $http Service to send data via REST Communication to Node Server. method: method, url: inserturl, data: jdata , headers: {'Content-Type': 'application/x-www-form-urlencoded'}, cache: $templateCache }). success(function(response) { console.log("success"); // Getting Success Response in Callback $scope.codeStatus = response.data; console.log($scope.codeStatus); }). error(function(response) { console.log("error"); // Getting Error Response in Callback $scope.codeStatus = response || "Request failed"; console.log($scope.codeStatus); }); $scope.list();// Calling the list function in Angular Controller to show all current data in HTML return false; }; $scope.list = function() { var url = 'http://localhost:1212/getangularusers';// URL where the Node.js server is running $http.get(url).success(function(data) { $scope.users = data; }); // Accessing the Angular $http Service to get data via REST Communication from Node Server }; $scope.list(); }
7.5. Angular Template and HTML
<html lang="en" ng-app="myApp"> .....
We refer to the Angular Application in above code.
<body ng-controller="UserListCtrl"> .....
We refer to the Angular Controller in above code.
Search:
<input ng-model="user"> <div class="span10"> <!--Body content--> <ul class="users"> <li ng-repeat="user in users | filter:user "> {{user.name}} </li> </ul> </div>
We have used the ng-repeat tag to take the users data model from the REST invocation.
<form name="myform" id="myform1" ng-submit="save()"> <fieldset> <legend>New User</legend> <div class="control-group"> <center><input type="text" placeholder="User…" ng-model="username" size=50 required/></center> <center><input type="text" placeholder="Password…" ng-model="password" size=50 required/></center> <center><input type="text" placeholder="Email…" ng-model="email" size=50 required/></center> </div> </fieldset> <p> <div><center><button type="submit" >Save now...</button></center></div> </p> </form>
We have used the ng-submit tag to send the user data model from the REST invocation and send to the node server in order to persist it in the NeDB database.
Please note that NeDB is just a light-weight Database which can be embedded in Node WebKit Applications. For fairly large scale database production systems, we should consider MongoDB.
8. Download the Source Code
This tutorial discussed Express.js and how to use it along with Node.js. You may download the source code here: Node.js-NeDB.zip