Learning Management Platform for Written Tutorial Series.

Node.JS REST API

Node.JS REST API

Introduction

REST APIs are everywhere. They make it easy for different systems to share data. REST is the acronym for Representational State Transfer. REST is a standard web architecture that uses HTTP Protocol.

In this tutorial, you will learn how to create a RESTful Node.JS APIs that use MySQL database on the back-end. Our API will be able to Create, Read, Update, and Delete (CRUD) data.

NodeJS REST API Add New Record

Topics to be covered

We will cover the following topics in this tutorial;

  • Tutorial Pre-requisites
  • RESTful API URLs
  • Modules required for our RESTful API
    • Restify
    • Restify Validator
    • Sequelize ORM
    • Sequelize CLI
    • MySQL
  • REST Client (Advanced Rest Client Google Chrome Extension)
  • Node.JS REST API CRUD example
    • Installing required modules using npm
    • Sequelize database migrations and seeds
    • Coding the server app

Tutorial Pre-requisites

For you to successfully complete this tutorial, you will need to know the following.

  • You have already installed the latest version of Node.JS. If you haven’t yet done so, then read the tutorial on how to install and configure Node.JS that guides you on how to download and install Node.JS
  • You have installed MySQL server and its up and running
  • Command line / terminal – Node.JS makes heavy use of the command line
  • Active internet connection – we need to download packages from the internet
  • A text editor / IDE – you need it to write code
  • JavaScript basic skills – you don’t need to be a JavaScript ninja to successfully complete this tutorial. Just the basics
  • A rest client application – we will need it to test the four HTTP verbs POST, GET, PUT, and DELETE.

RESTful API URLs

A RESTful API uses HTTP verbs POST, GET, PUT, and DELETE to represent data. We will create a simple app that manages contact details. Our API will have the following URLs

S/N URI HTTP VERB DESCRIPTION PARAMETERS
1 /contacts GET Returns all contacts None
2 /contacts/:id GET Returns single contact filtered by id Contact id
3 /contacts POST Creates a new contact Contacts table field names as string values
4 /contacts/:id PUT Updates an existing contact Contact id
5 /contacts/:id DELETE Deletes an existing contact Contact id

API versioning

APIs expose your data to multiple systems that other apps use. Versioning allows us to provide backwards compatibility. Suppose you create an API that returns three fields and you need to drop one field and add two more fields. This would break the applications that are using your system.

If you use versioning, you can leave version 1 of the API the way it is and make the changes in the next version 2.

Towards that end, our qualified API URLs will be as follows

http://localhost:8080/api/v1/contacts

HERE,

  • /api/v1/ prefixes all URLs with api followed by the version number.

Modules required for our RESTful API

Let’s now look at the modules that will be required to succesffully build our RESTful API.

  • Restify – this module provides us with a skeleton that we can use to build REST APIs in Node.JS. You can get more information about Restify from the official website http://restify.com/
  • Restify Validator – we will need this module to perform validation such as required fields, valid email address etc.
  • Sequelize ORM – Sequelize is an Object Relational Mapper that will provide mechanisms for interacting with the database.
  • Sequelize CLI – this module will enable us to use the command line to perform tasks such as create migrations, seeds and execute other tasks.
  • MySQL – our database is powered by MySQL.

REST Client (Advanced Rest Client Google Chrome Extension)

Feel free to use any REST client of your choice but for this tutorial, I will be using Advanced REST Client Google Chrome Extension.

You can load the following URL in Google Chrome web browser to download the extension.

https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

Node.JS REST API CRUD example

Let’s now get our hands dirty. If you have been following the tutorial series, then you already created a directory node on the drive of your choice. I will be using the same directory for this tutorial.

Open the command prompt

Run the following command to browse to the node directory. Note: I am using windows operating system but the command should still be able to work on other operating systems with minimal modifications

cd C:\node

run the following command to create a new directory rest

mkdir rest

Run the following command to access the directory that we just created

cd rest

Let’s now use npm to initialize the project. Run the following command

npm init

Respond to the utility questions and say yes to create the package.json file

Installing required modules using npm

Let’s now install the required modules. Run the following command

npm install restify restify-validator sequelize sequelize-cli mysql -g –save

HERE,

  • The above command installs multiple packages at once using npm. The packages are installed globally and added to package.json as project dependencies.

Sequelize database migrations and seeders

Migrations are used to automate creating and managing databases. Seeders are used to create dummy data for testing purposes.

Let’s first create the database in MySQL.

Run the following SQL command

CREATE SCHEMA node_rest_api;

Let’s now initialize our project using sequelize cli

Run the following command

sequelize init

HERE,

  • The above command will create the directories config, migrations, models, and seeders. The config directory will contain a config.json file that has database connection settings, models will have an index.js file that will load the configuration file and all our models

Open the file /config/config.json

Modify the development settings as follows

{
  "development": {
    "username": "root",
    "password": "melody",
    "database": "node_rest_api",
    "host": "127.0.0.1",
    "dialect": "mysql"
},…

HERE,

  • We set the username, password, database name, host and dialect that sequelize that use. Make sure the above settings match the ones on your development environment.

Let’s now create a model and migration file for the contacts table

Run the following command

sequelize model:create --name Contact --attributes first_name:string,last_name:string,mobile_no:string,email:string

HERE,

  • sequelize model:create name Contact creates both the model and migration for the table contacts. –attributes... is used to specify the table columns and their respective data types.

The models and migrations directories will now contain contact.js and 20160630101641-create-contact.js respectively. Note the timestamp depends on your system date.

Run the following command to create the database table automatically

sequelize db:migrate

HERE,

  • The above command uses the db: function to load the database configurations the call the migrate method that executes all pending migration files.

If you check the node_rest_api database in MySQL, it will contain two tables namely

  • contacts – this is the table that was created. Note: the table name is plural while the model name is singular. This is a standard convention when working with most ORM frameworks.
  • sequelizemeta – contains meta data about the already executed migration files.

Let’s now add dummy records to the database

Run the following command to create a contacts table seeder

sequelize seed:create --name contacts_seeder

HERE,

  • The above command creates a seeder file in seeds directory

Open the new file in /seed/20160630102529-contacts_seeder.js

Modify the code to the following

'use strict';

module.exports = {
    up: function (queryInterface, Sequelize) {
        return queryInterface.bulkInsert('contacts', [
            {
                first_name: 'John',
                last_name: 'Doe',
                mobile_no: '911',
                email: 'john@example.com'
            },
            {
                first_name: 'Jane',
                last_name: 'Doe',
                mobile_no: '912',
                email: 'jane@example.com'
            },
            {
                first_name: 'Adam',
                last_name: 'Smith',
                mobile_no: '913',
                email: 'adam@example.com'
            }
        ], {});

    },

    down: function (queryInterface, Sequelize) {
        return queryInterface.bulkDelete('contacts', null, {});
    }
};

HERE,

  • up: function(...) method is used to insert records into the contacts table
  • down: function(...) method is used to rollback what was done using the up method. In this case, we delete all records from the contacts table.

Run the following command to add the dummy records to the database.

sequelize db:seed:all

This will run all the files in seeds directory

Check the contacts table in the database. You will get the following records.

Coding the server app

Let’s modify the file that loads the models to make sure it loads the correct path.

Open /models/index.js

Locate the following line

var config = require(__dirname + '/..\config\config.json')[env];

Modify it to the following

var config = require('../config/config.json')[env];

Create a new file app.js in the root directory

The file app.js will have the following code structure

var restify = require('restify');
var restifyValidator = require('restify-validator');
var util = require('util');

var models = require('./models/index');

var error_messages = null;

function getAllContacts(request,response,next){...}
function getContact(request,response,next){...}
function verifyRequiredParams(request){...}
function addContact(request,response,next){...}
function updateContact(request,response,next){...}
function deleteContact(request,response,next){...}

var server = restify.createServer();

server.use(restify.bodyParser());
server.use(restify.queryParser());
server.use(restifyValidator);

server.get('/api/v1/contacts',getAllContacts);
server.get('/api/v1/contacts/:id',getContact);
server.post('/api/v1/contacts',addContact);
server.put('/api/v1/contacts/:id',updateContact);
server.del('/api/v1/contacts/:id',deleteContact);

server.listen(3000, function() {
    console.log('REST API Server listening at http://localhost:3000');
});

HERE,

  • var restify = require('restify'); imports the restify module
  • var restifyValidator = require('restify-validator'); imports the restify-validator module
  • var util = require('util'); imports the util module
  • var models = require('./models/index'); loads all the available modules into the variable models.
  • var error_messages = null; defines the variable used to store validation errors
  • function verifyRequiredParams(request){...} defines the function that checks if the client request has supplied all the required values and they are of the correct data type
  • function getAllContacts(request,response,next){...} defines the function that is executed when a user makes the request to the URI /api/v1/contacts using the GET HTTP verb
  • function getContact(request,response,next){...} defines the function that is executed when a user makes the request to the URI /api/v1/contacts/:id using the GET HTTP verb
  • function addContact(request,response,next){...} defines the function that is executed when a user makes the request to the URI /api/v1/contacts using the POST HTTP verb
  • function updateContact(request,response,next){...} defines the function that is executed when a user makes the request to the URI /api/v1/contacts/:id using the PUT HTTP verb
  • function deleteContact(request,response,next){...} defines the function that is executed when a user makes the request to the URI /api/v1/contacts/:id using the DELETE HTTP verb
  • var server = restify.createServer(); creates a server object and assign it to the variable server.
  • server.use(restify.bodyParser());,server.use(restify.queryParser());,server.use(restifyValidator); runs the handlers to handling parameters and validation
  • server.HTTP_VERB('/api/v1/contacts…) defines the respective route for the requested HTTP verb.
  • server.listen(3000, function() {…} starts listening on port 3000

The complete code for app.js is as follows

var restify = require('restify');
var restifyValidator = require('restify-validator');
var util = require('util');

var models = require('./models/index');

var error_messages = null;

function getAllContacts(request,response,next){
    models.Contact.findAll({})
        .then(function(contacts) {
        var data = {
            error: "false",
            data: contacts
        };

        response.send(data);
        next();
    });
}

function getContact(request,response,next){

    models.Contact.find({
        where: {
            'id': request.params.id
        }
    }).then(function(contact) {
        var data = {
            error: "false",
            data: contact
        };

        response.send(data);
        next();
    });
}

function verifyRequiredParams(request){
    request.assert('first_name', 'first_name field is required').notEmpty();
    request.assert('last_name', 'last_name field is required').notEmpty();
    request.assert('mobile_no', 'mobile_no field is required').notEmpty();
    request.assert('email', 'email field is required').notEmpty();
    request.assert('email', 'valid email address is required').isEmail();

    var errors = request.validationErrors();
    if (errors) {
        error_messages = {
            error: "true",
            message : util.inspect(errors)
        };

        return false;
    }else{
        return true;
    }
}

function addContact(request,response,next){
    if (!verifyRequiredParams(request)){
        response.send(422,error_messages);
        return;
    }

    models.Contact.create({
        first_name: request.params['first_name'],
        last_name: request.params['last_name'],
        mobile_no: request.params['mobile_no'],
        email: request.params['email'],
    }).then(function(contact) {
        var data = {
            error: "false",
            message: "New contact created successfully",
            data: contact
        };

        response.send(data);
        next();
    });
}

function updateContact(request,response,next){
    if (!verifyRequiredParams(request)){
        response.send(422,error_messages);
        return;
    }

    models.Contact.find({
        where: {
            'id': request.params.id
        }
    }).then(function(contact) {
        if(contact){
            contact.updateAttributes({
                first_name: request.params['first_name'],
                last_name: request.params['last_name'],
                mobile_no: request.params['mobile_no'],
                email: request.params['email'],
            }).then(function(contact) {
                var data = {
                    error: "false",
                    message: "Updated contact successfully",
                    data: contact
                };

                response.send(data);
                next();
            });
        }
    });
}

function deleteContact(request,response,next){
    models.Contact.destroy({
        where: {
            id: request.params['id']
        }
    }).then(function(contact) {
        var data = {
            error: "false",
            message: "Deleted contact successfully",
            data: contact
        };

        response.send(data);
        next();
    });
}

var server = restify.createServer();

server.use(restify.bodyParser());
server.use(restify.queryParser());
server.use(restifyValidator);

server.get('/api/v1/contacts',getAllContacts);
server.get('/api/v1/contacts/:id',getContact);
server.post('/api/v1/contacts',addContact);
server.put('/api/v1/contacts/:id',updateContact);
server.del('/api/v1/contacts/:id',deleteContact);

server.listen(3000, function() {
    console.log('REST API Server listening at http://localhost:3000');
});

Spinning the API

Let’s now take our API for a spin

Open the REST Client Application.

Load the following URL

http://localhost:3000/api/v1/contacts

You will get the following response

NodeJS REST API

Let’s now add a new record using our API

Change the HTTP Verb to POST and send the request without submitting any parameters

NodeJS Restify validator

You will get the above JSON response with a 422 response code.

Make another API call and submit all of the required parameters

You will get a response similar to the following

NodeJS REST API Add New Record

Summary

In this tutorial, we created a simple yet powerful NodeJS REST API that can create, read, update and delete records from the database. We also looked at how we can work with Sequelize ORM

What’s next?

If you found this tutorial useful, support us by using the social media buttons to like and share the tutorial. If you didn’t find it useful, please use the comments section below to let us know how we can do better next time.

Subscribe to our newsletter, like our Facebook fan page or follow us on Twitter to get free updates when we publish new tutorials

Tutorial History

Tutorial version 1: Date Published 2016-08-02


...