by Paul Oluyege June 14, 2020

What You Will Build

In this article, we shall be building a secure restful API from scratch (i.e., from an empty directory), then go through all the steps needed to build a secure RESTful API for a To-do list application whose front end will later be written in the coming part of this article. You will be able to create, retrieve, update, and delete a list.

Prerequisites

In other to follow along with this article, prior knowledge around JavaScript and an ideal understanding of Nodejs is needed or required you might not understand the article well and it might make sense to learn about it first. The code and the concepts explained in this article are not complex, therefore, with a previous experience with JavaScript, and a bit know how about Node.js, you won't have a hard time here.

Aside that, you will need to have a code editor (Visual studio code is recommended), Node.js, NPM(If you don't have these, please, follow the instructions over here.) and Postman installed in your machine. We shall use MongoDB Atlas, a cloud database for data persistent. Therefore, if you have an existing MongoDB Cloud Account, use your credentials to login into MongoDB Atlas dashboard, If you don't, go to the signup page (https://www.mongodb.com/cloud/atlas) for Mongo DB Atlas. It's free and no credit card required.

Introduction to RESTful API

In case you're new to RESTful APIs, Lets have a quick head start with brief definition and explanation of RESTful APIs. API (Application Programming Interface) is a set of subroutines and protocols that makes communication between two components possible. REST (Representation State Transfer) can be said to be an architectural style that defines a set of restrictions based on HTTP (Hypertext Transfer Protocol). Therefore, An API is said to be RESTful if it design is based on REST.

Taking advantage of a REST API design is now made easy because there's is no need to install libraries or additional software to that. Building APIs that meet your needs and that of your diverse customers has been made simple due to the freedom and flexibility that exist in REST API design.

CRUD (Create, Read, Update and Delete) HTTP methods like GET, POST, PUT, DELETE operations available for mutation, creation, and deletion respectively. REST stateless protocol and its interaction through standard operations on resources make the systems achieve scalability, fast performance and reliability.

For more information on the design concepts, you can read up on Representational state transfer and Richardson Maturity Model

Getting Started with Building RESTful APIs

Outline - Create DB Cluster on MongoDB Atlas - Cloud Database - Connect Application to MongoDB Atlass - Create Schema and Model - Create Express HTTP Server Application - Define API Endpoint and Routes - Create Controller functions - Import Controllers functions App Routes - Import DB Connection into Server - Test API on Postman

Todo-API Application Folder Structure

Starting from scratch, let’s create our project directory named Todo-API and run some commands on the terminal.

>> mkdir -p api/{controllers,models,routes}

>> touch api/controllers/todoController.js api/models/todoModel.js api/routes/todoRoutes.js

>> mkdir config

>> touch config/db.js

>> touch server.js

At the end of this, our expected file structure is seen below

Todo-API/
├──api/
│      ├── controllers/* API Controller folder
│      │                 └── todoController.js  * Todo controller file 
│      │ 
│      ├── models/  * API Model folder
│      │                  └── todoModel.js  * Todo model file   
│      │    
│      ├── routes/  * API route folder
│      │                  └──todoRoutes.js  * Todo route file  
│      │  
├── config/
│                  └──db.js  * Db connection file
│      │
├── package.json  * Defines our JavaScript dependencies
├── package-lock.json  * ----------
├── server.js  * API server file

All your files and folders are presented as a tree in the file explorer. You can switch from one to another by clicking a file in the tree.

Initialize package.json file and install dependences

>> npm init

>> npm install mongoose express body-parser

Breifly before we delve into writing code, Lets quicly connect out create a cluster in MongoDB Atlas cloud database.

Create DB Cluster on MongoDB Atlas - Cloud Database

After setting up a MongoDB Atlas account, the next is to create Clusters, but before we dive in, lets define clusters, Clusters are a set of MongoDB server that applications can connect with. The available clusters are of three types, they are shared, dedicated and production cluster. The only freely available among these is the shared clustered.

To create a free tier cluster, let's do the following:

  • Visit https://www.mongodb.com/cloud/atlas/register as a new user or https://account.mongodb.com/account/login?nds=true to login as a returning user to access the dashboard
  • Click Build New Cluster button and input the Project name
  • Select any free tire available and click Next Cluster tier button.
  • Select M0, a shared Cluster (for the purpose of this course) and click Create cluster button
  • Now that Cluster is created. Select Security tab for IP Whitelist setting and Add whitelist IP

After Cluster has been created, then its time to get started with connecting our cloud database with the application.

Connect Application to MongoDB Atlass

We can establish connections with applications using middleware such as the native MongoDB driver and Mongoose but, in this article, we shall use Mongoose default method to create model. Open db.js and do as shown in the snippet below

// Export mongoose
const  mongoose = require("mongoose");

//Assign MongoDB connection string to Uri and declare options settings
var  uri = "mongodb+srv://buddy-works:fabregas10@cluster0-8iysb.mongodb.net/test?retryWrites=true&w=majority"

// Declare a variable named option and assign optional settings
const  options = {
useNewUrlParser:  true,
useUnifiedTopology:  true
};

// Connect MongoDB Atlas using mongoose connect method
mongoose.connect(uri, options).then(() => {
console.log("Database connection established!");
},
err  => {
{
console.log("Error connecting Database instance due to:", err);
}
});

Run node db.js inside the config folder to test the connection > >> node db.js

database connection

After a successful connection has been established, next is to create and define schemas with Mongoose

Create Schema and Model

To get started with this, let's open todoModel.js file in the model folder and do and do as shown in the snippet below.

'use strict';
// Import mongoose
    const mongoose = require("mongoose");

// Declare schema and assign Schema class
    const Schema = mongoose.Schema;

// Create Schema Instance and add schema propertise
    const TodoSchema = new Schema({
        text: {
            type:String,
            required:true
        },
        status:{
            type:Boolean,
            required:true
        },
        createdOn: {
            type:Date,
            default:Date.now
        }
    });

// create and export model
module.exports = mongoose.model("todoModel", TodoSchema);

The previous steps has handled database cluster creation, database connection, schema and model creation, Next is to create our Express HTTP Server application.

Create Express HTTP Server Application

Express Js provide robust set of features for building of web applications. For the application we are building, our major need is to be able to send and receive HTTP requests, Therefore, to meet this need, a third-party middleware is used on the Express application object. For example, body-parser is a middleware that extracts the body of an incoming request and exposes it on res.body and parses the JSON, buffer, string, and URL encoded data that's submitted using a HTTP POST request.

Recall that we've already installed bodyParser alongside all dependencies needed.

Therefore, let's open server.js file, and follow the major steps involved in creating an express application server which can also be used to create our Todo application API as shown in the snippet below.

'use strict'

// require express and bodyParser
const  express = require("express");
const  bodyParser = require("body-parser");

// create express app
const  app = express();

// define port to run express app
const  port = process.env.PORT || 3000;

// use bodyParser middleware on express app
app.use(bodyParser.urlencoded({ extended:true }));
app.use(bodyParser.json());

// Add endpoint
app.get('/', (req, res) => {
res.send("Hello World");
});

// Listen to server
app.listen(port, () => {

console.log(`Server running at http://localhost:${port}`);
});

To test the express server, run the command > >> node server.js

if the steps has been followed perfectly, you should have the response - _Server running at http://localhost:3000

command output

Therefore, go to http://localhost:3000 on your browser to to view the output.

browser output

If you've been able to follow the steps in the snippet above, then you've got a basic understanding of how to develop an Express HTTP server, Next is to modify the server.js file and update it with a defined API endpoints and routes.

Define API Endpoint and Routes

Endpoint definition is a major step in creating APIs, this is where we define the endpoints to be exposed. For the Todo Application, will shall allow users to perform CRUD operations. The endpoints(based on todo model propertise) we’ll need are:

/todos

MethodDescription
GETFind all todos
POSTCreate a new todo

/todos:id

MethodDescription
GETFind a todo by id
PUTUpdate a todo status by id
DELETEDelete a todo by id

Now that we have defined API endpoints, the next is to create controller function for those endpoints.

Create Controller functions

Controllers are functions that handles incoming HTTP requests and send response back to the caller. Open the todoModel.js file and define controller functions.

// import Todo Model
const  Todo = require("../models/todoModel");

// DEFINE CONTROLLER FUNCTIONS

// listAllTodos function - To list all todos
exports.listAllTodos = (req, res) => {
Todo.find({}, (err, todo) => {
if (err) {
res.status(500).send(err);
}
res.status(200).json(todo);
});
};

// createNewTodo function - To create new todo
exports.createNewTodo = (req, res) => {
let  newTodo = new Todo (req.body);
newTodo.save((err, todo) => {
if (err) {
res.status(500).send(err);
}
res.status(201).json(todo);
});
};

// updateTodo function - To update todo status by id
exports.updateTodo = (req, res) => {
Todo.findOneAndUpdate({ _id:req.params.id }, req.body, { new:true }, (err, todo) => {
if (err) {
res.status(500).send(err);
}
res.status(200).json(todo);
});
};

// deleteTodo function - To delete todo by id
exports.deleteTodo = async ( req, res) => {
await  Todo.deleteOne({ _id:req.params.id }, (err) => {
if (err) {
return res.status(404).send(err);
}
res.status(200).json({ message:"Todo successfully deleted"});
});
};

Next is to import the controller functions into the route file.

Import Controller functions into App Route

Open the todoRoutes.js file and updates as follows

'use strict';

// create App function
    module.exports = function(app) {
        var todoList = require('../controllers/todoController');

// todoList Routes

// get and post request for /todos endpoints
        app
        .route("/todos")
        .get(todoList.listAllTodos)
        .post(todoList.createNewTodo);

// put and delete request for /todos endpoints
        app
        .route("/todo/:id")
        .put(todoList.updateTodo)
        .delete(todoList.deleteTodo);
    };

Import DB connection and API Route into Server

Before we test our API, lets Updates the server.js file, Add db connection file import before the express app creation line and also add API route import after.

// Import DB Connection
require("./config/db");

// Import API route
var routes = require('./api/routes/todoRoutes'); //importing route
routes(app);

At this junction, all the code is completed, Lets run and Test the API. If all has been rightly done, then we should have the output command as shown below

command output

Test API on Postman

Test for POST,GET,PUT and DELETE Requests on todo API for POST request on todo API - localhost:3000/todos POST request on "/todos"

for GET request on todo API - localhost:3000/todos GET request on "/todos"

for PUT request on todo API - localhost:3000/todo:id PUT request on "/todo:id"

for DELETE request on todo API - localhost:3000/todo:id DELETE request on "/todo:id"

Author: Paul Oluyege

Paul Oluyege

Paul is a full-stack software engineer, technical author and developer advocate who currently works as the software engineering lead in a top consumer credit company in Nigeria. With over 7 years of experience in all fields of the software life cycle, He has played integral roles in building well-tested, rock-solid software projects and web and mobile solutions using Javascript technologies stack (MEAN - Mongo, Express, Angular, Node), PHP/Laravel and Ionic Framework. Paul is dedicated to constantly improving tools and infrastructure to maximize productivity, minimize system downtime, and quickly respond to the changing needs of the business. He is a proactive problem solver and determined achiever who is looking for opportunities to prove himself.