HomeAbout Me

Build Rest API from scratch in Node.js

By Arvind Pandey
Published in Programming
July 24, 2020
4 min read

Scope of this tutorial


  1. Node.js setup
  2. Building REST API for a todo app using express.js
  3. Error handling
  4. Test API using postman REST client

What is not in the scope

  1. Using database with node.js
  2. Authentication for API

What is Node.js?


Node.js is runtime environment for Javascript. It became quite popular from its inception in 2009.
For detailed history you can read it here

What is Express.js


Express.js is unopinionated web development framework. It’s built on top of the Node.js. We could ideally write our code in pure Node.js code but we might end up building another express.js. Because express.js is already quite popular and well tested, we will use its power and capability to build APIs faster.

Node.js Setup


Download the node.js installer from this link.

To verify that node is installed successfully, type node in the terminal or console. It should enter to node console where you can run write javascript code snippets and run it.

Arvinds-MacBook-Pro:cscamp.org arvind$ node
>

If you see anything else then there is some problem with your setup.

Building REST API for a todo app using express.js


API Signatures:


Before building the actual APIs, let define the contract. Contract is nothing but agreeing product’s interface and what it will return.

// CRUD
POST /todos   // C --> Create
GET /todos    // R --> Read
GET /todos/:id // R --> Read
PUT /todos/:id      // U --> Update
DELETE /todos/:id  // D --> Delete

Setup the project


a. Create a directory called todo-app

mkdir todo-app

b. Go inside the directory

$ cd todo-app

c. Create a npm project using npm init command. Provide on screen inputs.

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (todo-app)
version: (1.0.0)
description: todo app
entry point: (index.js) app.js
test command:
git repository:
keywords:
author: Arvind Pandey
license: (ISC)
About to write to /Users/arvind/Documents/todo-app/package.json:

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "todo app",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Arvind Pandey",
  "license": "ISC"
}

This will create a file called package.json This file is a kind of manifest of the application.

If you look at the content of the package.json, it would similar to below file content.

{
  "name": "todo-app",
  "version": "1.0.0",
  "description": "todo app",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Arvind Pandey",
  "license": "ISC"
}

The interesting thing here is the entry point app.js We will come to that very soon.

Add express.js to the project


We need to add express.js to the project before we proceed further. Run below command.

npm install express --save

It will install latest stable express version and it will add express as dependency in package.json.

Creating the express app


Now is the time to write some code. Create app.js and write below code.

const express = require('express');
const app = express();
const PORT = 4000;
app.listen(PORT, ()=>{
console.log(`Listening on port ${PORT}`);
})

Let’s go line by line to see what’s happening.
Line 1: It’s very similar to import statement in Java. We are getting the reference of express library. That we will use to create the app.
Line 2: Creating the app by invoking the express().
Line 3: Defining a variable PORT that we will use to run our app on.
Line 4: Invoking listen() function to bind a port to the app.
Line 5: listen() function accepts 2 arguments. First argument is the port and second is a call back function. Line 5 is the body of the call back function. Not doing anything fancy, just printing some message on the console.

Start the server with below command.

node app.js

If you see below message on the console then your server started successfully. Yay!

$ node app.js 
Listening on port 4000

Adding the first route


If we understand the first route, others will be quite similar.

Let’s add root route to our app. When some hits the root path what do we want to return.

app.get('/', (req, res) => {
  res.send({'path':'home page'});
});

Let’s see what is happening.

  1. app.get() is telling this is going to define a get call.
  2. The first argument to the get() is the part.
  3. The second argument is the call back function, where we handle the request and response.

The first argument is the request object and second is the response object. We are not expecting anything from request object so, we are not bothering it.

We are just sending back the sample json response.

Stop the server and restart again.

node app.js

Go to the browser and hit the url http://localhost:4000/

You should see the below json response on your browser.

{
  "path": "home page"
}

That concludes the first route. It was quite minimal and easy to digest. (I hope so!).

We are going to cover remaining routes. Before that install an API client like postman to test the rest interface.

ToDo - The Model


The typical todos just contain the list of tasks to accomplish. For us just one field is enough to store the data, the task field. Because we are not dealing with database here, we expect id also to be passed when creating the To-Do.

Below is the sample POST request body.

{
  'id': '1',
  'task': 'write article on javascript'
}
Storing the To-Dos

We will store all the To-Dos in an array of objects.

Create ToDos - POST /todos


Add below code snippet to app.js file. Restart the server.

app.use(express.json());
let todos = [];
app.post('/todos', (req, res) => {
  todos.push(req.body);
  res.send({ 'message':'success' } );
})

This does the very minimum thing. If you try doing a post call using postman client, you should be able to post the todos.

Error handling

There are so many things wrong about the code above. Here are few of them.

  1. Id is not mandatory, will be difficult to track todos.
  2. It accepts duplicate ids, that means you cann’t differentiate one todo with other.
  3. It can create todos without task field. Without task value, todos are of no value.
  4. What if something goes wrong while posting, we are not handling the error scenarios.

Keeping that in the mind, here is few things, we should do to make it more robust.

  1. Check for the id to be present in the body
  2. Check for task field is not empty
  3. Do not allow duplicate ids.
  4. Handle the error and set the status code correctly.

Below code snippet does the basic house keeping that is mentioned above.

app.use(express.json());
let todos = [];
app.post('/todos', (req, res) => {
  try {
    if(req.body.id == null || req.body.task == null) {
      res.json({'message':'id and task fields are mandatory to pass in the body'});
      return;
    }
    if (todos.filter((item) =>req.body.id == item.id).length > 0) {
      res.status(500);
      res.json({'error':'use unique id'});
    } else {
      todos.push(req.body);
      res.json({ 'message':'success' } );
    }
  } catch (error) {
    res.status(500);
    res.json({'error':'something went wrong'});
  }
})

app.listen(PORT, ()=>{
  console.log(`Listening on port ${PORT}`);
})

Now, our POST API is in good shape. You can try with postman. Test both positive and negative scenarios.

That concludes the first route.

Retrieve all the ToDos - GET /todos


Now that we have created the todos, we need API to get all the todos. We need define a GET API call.

Copy and paste below code snippted and restart the server.

app.get('/todos', (req, res) => {
  res.send(todos);
});

Now, restart you server. Using postman perform below steps.

  1. Create some todos using POST /todos API
  2. Get all todos using GET /todos

Get a todo by its id - GET /todos/:id


We can retrieve a todo by its id. Below is the code snippted. You can copy and past to app.js

app.get('/todos/:id', (req, res) => {
  try {
    if (todos.filter((item) =>req.params.id == item.id).length > 0) {
      let r = todos.find(item => item.id == req.params.id);
      res.send(r);
    } else {
      res.send({'message': `no result found with id: ${req.params.id}`});
    }
  } catch (error) {
    res.status(500);
    res.json({'error':'something went wrong'});
  }
});

Update a particular todo - PUT /todos/:id

app.put('/todos/:id', (req, res) => {
  try {
    if(req.body.task == null) {
      res.json({'message':'id and task fields are mandatory to pass in the body'});
      return;
    }

    if (todos.filter((item) =>req.params.id == item.id).length > 0) {
      todos.find(item => item.id == req.params.id).task = req.body.task
      res.json({'message':'update successful'});
    } else {
      res.json({'message': `no todo found with id: ${req.params.id}`});
    }
  } catch (error) {
    res.status(500);
    res.json({'error':'something went wrong'});
  }
})

Delete a todo - DELETE /todos/:id

app.delete('/todos/:id', (req, res) => {
  try {
    if(todos.filter(item => item.id == req.params.id).length > 0) {
      let r = todos.filter(item => item.id != req.params.id);
      todos = [...r];
      res.json({'message':'success'});
    } else {
      res.json({'message': `no todo found with id: ${req.params.id}`});
    }
  } catch (error) {
    res.status(500);
    res.json({'error':'something went wrong'});
  }
})

Testing the API using postman

We have covered all the routes. Let’s test each route one by one.

I hope you have already installed Postman client.

Create Todos - POST /todos


POST Call
POST Call

Get Todos - GET /todos


GET Call
GET Call

Update a Todo - PUT /todos/:id


GET Call
GET Call

Delete a Todo - DELETE /todos/:id


GET Call
GET Call

You can find complete source code at Github. Here is the link.


Happy Learning!


Tags

#node.js#programming#javascript
Previous Article
Data Structure Fundamentals in Java

Topics

Life & Productivity
Programming
Running

Related Posts

Data Structure Fundamentals in Java
July 18, 2020
1 min
Arvind Pandey © 2022, All Rights Reserved.

Quick Links

About Me

Social Media