Build A RESTful Api With Node.js And Express.Js Part One

In this tutorial, we’ll be learning how to build a Rest API in Node.js and Express.js by building a simple todo app API. This tutorial assumes an intermediate knowledge of javascript and experience working on the command line. The source code for the final project can be found here .

Getting Started

To get started create a new folder and call it todo.

$ mkdir todo
$ cd todo

In your todo folder create a new file called app.js

$ touch app.js

The next thing for us to do is to install Node. you can install node here. After node has been installed then we’ll install express with npm. Node comes with npm so we won’t need to install npm.

Initialize The App

Navigate on the command line to the root of your app and run.

npm init 

Click the return key repeatedly for every questions asked of you on the command line.

This will create a package.json file for you.

Install Dependencies And Set Up Babel

$ npm install express —-save

We’ll also need to install babel because we’ll be writing ES6 syntax, Babel helps to turn our codes from ES6 to ES5. why do we have to compile our code down to ES5 ? well, there are some ES6 features that our browsers and node are yet to understand, and older browsers do not understand ES6 codes, so we use babel to compile our code to ES5 so that both old browsers and new browsers can understand. Our Purpose for using babel here is so that ES6 features that are not part of node yet can be compiled down to ES5 that node understands.

$ npm install babel-cli --save

We’ll also be installing babel-preset-es2015, the presets contains a set of plugins, these plugins are for ES6 features, by installing and configuring babel-preset-es2015 we tell babel to convert any ES6 feature we use that are contained in the preset to their ES5 equivalent.

$ npm install babel-preset-es2015 --save

Now we need to create a .babelrc file, in the babelrc file, we’ll set babel to use the es2015 preset we installed as its preset when compiling to ES5.

At the root of our app, we’ll create a .babelrc file.

$ touch .babelrc

In the babelrc file type the following to set up your preset.

{  
"presets": ["es2015"]
}

This tells babel to use es2015 as its preset, note that ES2015 is another name for ES6.

Create A Dummy Database

The last thing we’ll need to do before we get started creating our Apis is to create a dummy database we’ll use.

Create a folder and name it db.

$ mkdir db

In the folder create a file and call it db.js

$ cd db
$ touch db.js

In db.js create a javascript object to create a dummy database

const todos =  [
{
id: 1,
title: "lunch",
description: "Go for lunc by 2pm"
}
];

export default todos;

Setup The App And Create Our First Endpoint

Now let’s get started creating our todo app

import express from 'express';
import db from './db/db';
// Set up the express app
const app = express();
// get all todos
app.get('/api/v1/todos', (req, res) => {
res.status(200).send({
success: 'true',
message: 'todos retrieved successfully',
todos: db
})
});
const PORT = 5000;

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

We imported express which we installed at the beginning of the course, app.get makes a get request to the server with the route/endpoint provided as the first parameter, the endpoint is meant to return all the todos in the database. The second parameter is a function that runs every time we hit that endpoint. the function takes two parameters which are req and res. The req object contains information about our request and the response object contains information about the response and methods we can use to send information back to the client.

res.status(200) is used to send back the status of the request, 200 means ok and it indicates a successful request. Status codes are ways for client like web app or mobile app to check wether things went wrong or not.if we get a 404(which means Not Found)we don’t need to check the payload because we know that nothing is coming that we are really interested in. If 200 comes back we can check the payload because we know we are expecting something. You can learn more about HTTP status codes here.

res.send() is used to send back a response to the client, the resource passed into the send as a parameter is what gets sent back to the client. in this case, we send back an object which contains some information, the todos property of the object contains the data we imported at the top of app.js from our dummy database.

app.listen creates a web server for us, it takes two parameters, the first parameter is the port we want our application to listen on t, whatever port we provide, in our case, 5000 will be the port our server will be running on in our system. the second parameter is optional, it is a callback function of what should happen when the server gets created, in our case we are logging a message to the console. when the sever gets created then we can access our endpoint ’/api/v1/todos’ from there. the server will run on a port 5000 on a localhost on our machine. so we’ll have our localhost:port/api route. The endpoint we created will be accessed like this localhost:5000/api/v1/todos.

Now to run this code let’s go to the command line.we’ll normally run our node app from the command line like this.

$ node app.js 

But this will throw an error because our code is in ES6, to successfully run our code we’ll have to run it with babel-node which will compile it to ES5. babel-node comes with the babel-cli which we installed at the beginning of the course.

$ node_modules/.bin/babel-node app.js

Now we can go to postman and test our endpoint, postman is an application we use to test our endpoints. you can download postman here.

To test the endpoint we’ll go to localhost:5000/api/v1/todos.

Take a look at the ‘GET’ before localhost:5000/api/v1/todos, remember our endpoint is a get request, that is why we set that dropdown to ‘GET, if our endpoint was a post request i.e we had app.post then we would have set that to POST.

Getting our server started by running this every single time is stressful, to simplify this process we are going to do two things, first, we are going to install nodemon, Secondly, we’ll create a script in our package,json to start our server.

Let’s install nodemon, run the following in your terminal.

$ npm install nodemon --save-dev

Nodemon watches your app for file changes and restarts the server every time a file changes in your app. This eases your work because you won’t have to start and restart the server manually every time you change files in your app

Lets create the script, in your package.json, inside the script part include this

"start": "node_modules/.bin/nodemon app.js --exec babel-node --"

You know what babel-node does.

Your package.json scripts should look like this

{
"name": "todo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js --exec babel-node --"
},
"author": "",
"license": "ISC",
"dependencies": {
"babel-cli": "^6.26.0",
"babel-preset-es2015": "^6.24.1"
"express": "^4.16.3"
}
}

Now every time we want to start our app we just run the following script on the terminal.

npm run start

This will run the start script in our package.json file.

Let’s create an endpoint to add todos, but before then let’s install a package called body-parser, body-parser parses incoming request bodies in a middleware before your handlers, available under the req.bodyproperty.

When you are sending data to the server, the data could be coming from a form or it could be a json, what body parser does is that it parses this data that is coming from the client in an object called req.body, so for example if I have a JSON data coming from the client to the server.

{
   "name": "Ola",
   "school": "unilag"
}

What body parser does is that it parses this JSON data and makes it available under the req.body as a property. remember req is the first property we provide for our callback when we make an API request, and remember I said req contains information about the request that is coming from the client, so body parser makes the data coming from the form or any JSON data coming from the client available as a property under the req.body, so we can access the JSON data from req.body as.

req.body.name
req.body.school

So lets install body-parser

$ npm install body-parser --save

Now lets import it in app.js

import bodyParser from 'body-parser';

Now we will configure body parser for our application like this.

const app = express();
// Parse incoming requests data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

Create Todo

Now lets get to creating an endpoint to create a todo.

app.post('/api/v1/todos', (req, res) => {
if(!req.body.title) {
return res.status(400).send({
success: 'false',
message: 'title is required'
});
} else if(!req.body.description) {
return res.status(400).send({
success: 'false',
message: 'description is required'
});
}
const todo = {
id: db.length + 1,
title: req.body.title,
description: req.body.description
}
db.push(todo);
return res.status(201).send({
success: 'true',
message: 'todo added successfully',
todo
})
});

In this endpoint, we are not making a request to the server to get data but rather we are posting data. just like we explained, the data coming in are parsed into req.body as properties, so we have req. body.title, etc.

We create a todo object with the information we got from the client through body-parser and then push it to the dummy db array as a new todo.

Let’s test this out in postman, we would have to pass in some data and send them to the server to test this out, on postman, when you select POST, click on n body before Headers which is before Authorization and pass in your values in the field.

localhost:5000/api/v1/todos, ensure you set the HTTP method in your postman to POST.

Take a look at the ‘POST’ before localhost:5000/api/v1/todos, remember our endpoint is a post request, that is why we set that dropdown to POST.Ensure the radio button x-www-form-urlencoded is checked or use raw where you would pass JSON data like this.

{
"title": "breakfast",
"description": "get breakfast"
}

Get A Single Todo

Now let’s create an endpoint to get a single todo from the database. Type the following:

app.get('/api/v1/todos/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  db.map((todo) => {
    if (todo.id === id) {
      return res.status(200).send({
        success: 'true',
        message: 'todo retrieved successfully',
        todo,
      });
    } 
});
return res.status(404).send({
   success: 'false',
   message: 'todo does not exist',
  });
});

Just, as usual, this endpoint takes two parameters, the route and the callback function. the different thing here is that the route in this endpoint has a :id, there are times we want to pass parameters to our endpoints because we will need them in our application, to pass those parameters we use :param.

The endpoint created above is meant to get a single todo, to get a single todo we’ll need a unique way to identify this todo in the database, so if we know the id of the todo we want to get we can then fetch it from the database, so every time we make a request to this endpoint we pass along the id of the todo we want to get, the callback function will then query the database for the todo with that application.

What is going on in the endpoint above is that we pass the id of the todo we want to get as a parameter to route, to get the value of id passed to the route we use req.params.id, req.params is an object that contains all the parameters passed to the routes, we convert the id to an int and then we loop through our dummy database db to find the todo whose id will be equal to the one we got from the URL, the matching todo is then returned as the single todo.

Let’s test this out, fetch the total todos in the database to see what we currently have.

Now let’s add a new todo to the database

Lets fetch all the todos in the database again

Now we have the new todo we just added to the database.

Let’s test our endpoint now, go to localhost:5000/api/v1/todos/:id, replace :id with the id of the todo you want to get. in our case the todo with and id of 2, Set the http method to GET.

Delete Todo

Now let’s create an endpoint to delete todos from the database.

app.delete('/api/v1/todos/:id', (req, res) => {
const id = parseInt(req.params.id, 10);

db.map((todo, index) => {
if (todo.id === id) {
db.splice(index, 1);
return res.status(200).send({
success: 'true',
message: 'Todo deleted successfuly',
});
    }
});


return res.status(404).send({
success: 'false',
message: 'todo not found',
});


});

So what are we doing here? well, basically we are passing the id of the todo we want to delete as a parameter to the route /api/v1/todos/:id. we fetch that id with req.params.id, So for us to delete an item with this id we have to first search for it in the database, we did that by mapping through the db array and check the id of the current todo in the iteration against the id we got from route till we find a match, we then use array method splice() to remove that item from the database. you can learn more about array.splice and how it works here. In the case where we do not find anything we return a message to the user stating ‘todo not found’.

Now lets test this out, first let’s fetch the todos in our database to see what we have.

Now lets add a new todo

let’s fetch all our todos again

As you can see we now have two todos in our database, the previous one that was there initially(we hard coded this in the app) is the todo with an id of 1, and the new one we added is the todo with an id of 2.

Now lets’s remove the todo with an id of 1 by going to the endpoint we just created. Navigate to localhost:5000/api/v1/todos/:id, the id in this case is 1, just replace :id with 1 in the endpoint.

Now let’s fetch all the endpoint to see if we truly deleted the todo.

Now we have only the todo with and id of 2.

Lets try to delete a Todo with an id that does not exist.

We get a message back that the todo is not found.

Update Todo

Now let’s create an endpoint to update todos.

app.put('/api/v1/todos/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
let todoFound;
let itemIndex;
db.map((todo, index) => {
if (todo.id === id) {
todoFound = todo;
itemIndex = index;
}
});

if (!todoFound) {
return res.status(404).send({
success: 'false',
message: 'todo not found',
});
}

if (!req.body.title) {
return res.status(400).send({
success: 'false',
message: 'title is required',
});
} else if (!req.body.description) {
return res.status(400).send({
success: 'false',
message: 'description is required',
});
}

const updatedTodo = {
id: todoFound.id,
title: req.body.title || todoFound.title,
description: req.body.description || todoFound.description,
};

db.splice(itemIndex, 1, updatedTodo);

return res.status(201).send({
success: 'true',
message: 'todo added successfully',
updatedTodo,
});
});

Just as usual we get the id of the todo we want to update from the URL, we loop through our dummy db to find the todo with that id, if we don’t find the todo then we return a message to the user saying todo not found. If we find the todo then we get new input supplied by the user, the new input is parsed by body parser to the req.body, we get the updated entries from req.body and create an updated todo object with it. We then use db.splice to remove the old todo that match our iteration when we looped through the dummy db and replace it with the updatedTodo that we created.

Let’s test this out.

Let’s get all the todos we have in our database currently, Note that every time your server restarts you lose the entries you have in memory, that’s why we lose todo we added through postman when our server restarts except for the one we hardcoded in the app.

Now lets update the todo with the id of 1.

Now we have come to the end of this tutorial, there is a second part to this tutorial and you can find it here. Thanks for your time and patience to go through this and I do hope you have learnt one or two things.