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.
We will cover the following topics in this tutorial;
For you to successfully complete this tutorial, you will need to know the following.
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 |
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.Let’s now look at the modules that will be required to succesffully build our RESTful API.
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
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
Let’s now install the required modules. Run the following command
npm install restify restify-validator sequelize sequelize-cli mysql -g –save
HERE,
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,
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 modelsOpen 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,
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,
If you check the node_rest_api
database in MySQL, it will contain two tables namely
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,
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 tabledown: 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.
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
modulevar restifyValidator = require('restify-validator');
imports the restify-validator
modulevar util = require('util');
imports the util
modulevar models = require('./models/index');
loads all the available modules into the variable models.var error_messages = null;
defines the variable used to store validation errorsfunction verifyRequiredParams(request){...}
defines the function that checks if the client request has supplied all the required values and they are of the correct data typefunction 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 verbfunction 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 verbfunction 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 verbfunction 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 verbfunction 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 verbvar 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 validationserver.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');
});
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
Let’s now add a new record using our API
Change the HTTP Verb to POST and send the request without submitting any parameters
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
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
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 version 1: Date Published 2016-08-02