How to Use Node.js, Fastify and Auth0 to protect REST API

How to Use Node.js, Fastify and Auth0 to protect REST API

I hope this helps you to add authentication to your own Fastify REST API.

With authentication, calling the API has to follow these steps:

  1. Before the workflow client can access the API of the workflow engine, it has to have an access token. If Auth0 authenticates the workflow client, it generates and returns an access token.
  2. The workflow client calls the workflow engine API and passes the access token. The workflow client adds the access token to the HTTP authorization header.
  3. The workflow engine validates the presented access token. If correctly validated, it performs the requested API method. The workflow engine returns the result to the workflow client.

OAuth 2.0 supports several different ways to retrieve an access token. Each of these ways — or flows — have a specific use case. OAuth 2.0 calls the flow from the example, the Client Credentials Flow. The workflow client uses a Client ID and Client Secret to request the access token.

For the next requests, the workflow client doesn’t have to request an access token. It can reuse the existing access token. For access tokens, we’re going to use JSON Web Tokens (JWT). JWT is a standard method for creating JSON-based access tokens.

Implementing OAuth 2.0 Using Auth0 in the Workflow Engine

To be able to add authentication in the workflow engine, we need the following:

  • An Auth0 account — they have a free plan for up to 7,000 active users
  • A registered application with Auth0
  • The npm package fastify-auth0-verify, a Fastify plugin for verifying JSON Web Tokens that are issued by Auth0.
Create an Auth0 account

To use Auth0, you have to create an account and application so you can integrate authentication into the API. Here, you can sign up for a free account. If you’ve added the account, you add the application by clicking on "+ Create Application.”

First, you have to enter the name of your application. Then, select “Machine to Machine Applications” as the application type. The application type defines which flow you can use to retrieve an access token. By choosing machine to machine, we can use the Client Credentials Flow.

Retrieve the domain and client secret

You need the domain and Client Secret to configure the[fastify-auth0-verify](https://github.com/nearform/fastify-auth0-verify) plugin. You can find both the Domain and Client Secret on the Settings tab of the application. See below.

Installing and configuring fastify-auth0-verify

Inside the workflow engine, I install fastify-auth0-verify using the standard npm command:

npm i fastify-auth0-verify

Then in server.js, add the following to register the plugin:

fastify.register(require('fastify-auth0-verify'), {
  domain: config.authprovider.domain,
  secret: config.authprovider.secret
});

fastify.addHook("onRequest", async (request, reply) => {
  try {
    await request.jwtVerify()
  } catch (err) {
    reply.send(err)
  }
});
Don’t put sensitive information in source control

The domain and secret are sensitive information that you shouldn’t put in source control. Instead, you should retrieve this information from the environment.

const constants = require('./constants');

// Container for all environments
const environments = {};

environments.production = {
  httpPort: process.env.HTTP_PORT,
  httpAddress: process.env.HOST,
  envName: 'production',
  log: {
    level: process.env.LOG_LEVEL,
  },
  database: {
    url: process.env.STORAGE_HOST,
    name: 'workflow-db',
    connectRetry: 5, // seconds
  },
  workflow: {
    pollingInterval: 10, // Seconds
  },
  authprovider: {
    domain: process.env.AUTH_DOMAIN,
    secret: process.env.AUTH_SECRET
  }
};

// Determine which environment was passed as a command-line argument
const currentEnvironment = typeof process.env.NODE_ENV === 'string' ? process.env.NODE_ENV.toLowerCase() : '';

// Check that the current environment is one of the environment defined above,
// if not default to prodution
const environmentToExport = typeof environments[currentEnvironment] === 'object' ? environments[currentEnvironment] : environments.production;

// export the module
module.exports = environmentToExport;

I prefer having a single configuration object that contains all settings instead of referencing process.env.* everywhere in my source-code.

Using a central configuration object makes managing settings more maintainable. The configuration object also gives an overview of all the configuration settings of the application.

Putting settings in your environment

Configuring a lot of settings in environment variables can become cumbersome. The library dotenv makes it easier by reading environment variables from an .env file. The library stores the variables from the file in process.env.

After installing the dotenv npm module, the command below reads the environment variables from the .env file and stores them in process.env. Make sure you execute this command as soon as possible in your Node.js application.

require('dotenv').config()
Testing the Authentication Using Postman

With the plugin fastify-auth0-verify registered and the domain and secret filled, we’re ready to test the authentication. Instead of using the workflow client, we’ll use Postman for testing.

Sending an unauthorized request

First, to verify the health endpoint is secured, I execute an HTTP GET request to the health endpoint ([http://localhost:8181/api/health](http://localhost:8181/api/health)). After clicking Send, the workflow engine responds with an HTTP response: 401 Unauthorized. The 401 indicates the API can’t be accessed. So our authentication is working.

Sending an authorized request

To perform an authorized request, we first have to request an access token from Auth0.

We request an Access Token by sending an HTTP POST to the token endpoint of the Auth0 subdomain. The body of your request should contain a JSON object with the client_id, client_secret, audience, and grant_type. You can find this information on the Settings tab of the application page. With "grant_type": "client credentials”, we state to Auth0 that we want to use the Client Credentials Flow.

If you have entered all the information, Auth0 returns a JSON object as a response that includes the access token. This is the access token we need to be able to call the API of the workflow engine. Copy the value of the access_token without the double quotes.

Now, we go back to the original request in Postman. Go to the Health endpoint of the workflow engine, and use the Access Token. You need to click on the Authorization tab in Postman and select Bearer Token for the TYPE. Paste the access token you got from the previous request in the Token field.

When you click Send, you’ll see you can call the Health endpoint. The Health API returns an HTTP status 200 OK. The body of the response contains the current date and time, indicating the API is working.

If you followed along, you’ll agree it’s easy to add authentication to your API when using an external authentication provider, such as Auth0.

I Don’t Want to Use an External Authentication Provider!

Not everyone can or wants to use an external authentication provider like Auth0. Instead, they want to use an on-premise authentication provider.

Luckily there are several other options, such as oidc-provider. oidc-provider is an OAuth 2.0-compatible authorization server for Node.js. For installation and configuration, I refer you to the documentation page. As we’re using open standards, it’s simple to replace Auth0 with this authorization server.

Conclusion

Thank you for reading. I hope this helps you to add authentication to your own Fastify REST API.

Creating a RESTful Web API with Node.js and Express.js from scratch

Creating a RESTful Web API with Node.js and Express.js from scratch

In this article, I’ll show you step by step how to create a RESTful Web API with Node.js and Express.js by building a simple and useful Todo API. This article assumes you have basic javascript knowledge and terminal using capabilities.

In this article, I’ll show you step by step how to create a RESTful Web API with Node.js and Express.js by building a simple and useful Todo API. This article assumes you have basic javascript knowledge and terminal using capabilities.

You can also build a Web API in Node.js by using another framework except Express.js but Express.js is one of the most popular web framework for Node.js.

You can found the final source code of this Web API in this github repository.

Let’s start to create our mentioned Web API.

Before start

If you have never used Node.js or npm package manager you should install them.

To check whether the Node.js is already installed on your computer, open your terminal and run node -v command. If you see your Node.js version it's installed. Otherwise go to below link.

Click here to download and install Node.js (You can choose LTS version)

And if you don’t have any IDE or text editor for writing javascript I advice you Visual Studio Code.

Click here to download VS Code (Optional)

About express-generator

In fact we could use <a href="https://expressjs.com/en/starter/generator.html" target="_blank">express-generator</a> tool which designed to creating an Express Web API quickly but I want to create this API from scratch because of that tool puts some extra files and folder structures that we don't need them now. But you can use this useful tool next time on creating new Web API. I won't use it now due to keep article simple.

Creating Project

Go to your workspace root folder and create a new folder there named "todo-api".

Then create "package.json" and "server.js" files into "todo-api" folder like below.

package.json

{
    "name": "todo-api",
    "version": "1.0.0",
    "scripts": {
        "start": "node server.js"
    },
    "dependencies": {
        "express": "^4.16.4"
    }
}

server.js

const http = require('http');
const express = require('express');
const app = express();
app.use(express.json());
app.use('/', function(req, res) {
    res.send('todo api works');
});
const server = http.createServer(app);
const port = 3000;
server.listen(port);
console.debug('Server listening on port ' + port);

After creating above files open your terminal in the "todo-api" folder and run npm installcommand.

This command will be install your project dependencies which pointed at the "package.json" file.

After finished package download process, downloaded dependency files will be installed into"node_modules" folder at the root of the "todo-api" folder.

After finished package installing then run npm start to start our Web API.

Now our Web API listening. To see result open your web browser then write localhost:3000 to address bar and press enter.

As result you’ll see our request handler response in your browser: “todo api works”.

This is a dead simple Express.js Web API. And it needs the some development. For example we need to an api endpoint to get todo items. So let’s add a new API endpoint for this.

Create a new folder named "routes" in the root of the "todo-api" folder.

Then create a "items.js" file inside of "routes" folder and put following codes inside it.

Your final folder structure should be like below;

/todo-api
/node_modules
/routes
    items.js
package.json
server.js

items.js

const express = require('express');
const router = express.Router();
const data = [
    {id: 1, title: 'Finalize project', order: 1, completed: false, createdOn: new Date()},
    {id: 2, title: 'Book ticket to London', order: 2, completed: false, createdOn: new Date()},
    {id: 3, title: 'Finish last article', order: 3, completed: false, createdOn: new Date()},
    {id: 4, title: 'Get a new t-shirt', order: 4, completed: false, createdOn: new Date()},
    {id: 5, title: 'Create dinner reservation', order: 5, completed: false, createdOn: new Date()},
];
router.get('/', function (req, res) {
    res.status(200).json(data);
});
router.get('/:id', function (req, res) {
    let found = data.find(function (item) {
        return item.id === parseInt(req.params.id);
    });
    if (found) {
        res.status(200).json(found);
    } else {
        res.sendStatus(404);
    }
});
module.exports = router;

Initial code of "items.js" file contains two endpoints. First one gets all todo items and second one gets one item which matches given id parameter.

Before testing items routes we should register it in the "server.js" file.

Modify "server.js" file like below to register new item routes.

server.js

const http = require('http');
const express = require('express');
const itemsRouter = require('./routes/items');
const app = express();
app.use(express.json());
app.use('/items', itemsRouter);
app.use('/', function(req, res) {
    res.send('todo api works');
});
const server = http.createServer(app);
const port = 3000;
server.listen(port);
console.debug('Server listening on port ' + port);

Now run npm start to start our Web API.

Then open your web browser and write localhost:3000/items to address bar and press enter.

You’ll see todo items json array in the response body.

And write localhost:3000/items/3 to address bar and press enter.

You’ll see the todo item which has id 3 in the response body.

But not finished up yet.

CRUD Operations and HTTP methods

I think we’ll need CRUD operations to Create, Read, Update and Delete todo items.

We have already two endpoints for getting items. So we need Create, Update and Delete endpoints.

Let’s add also these endpoints into the items.js file.

Our final "items.js" file and endpoints should be like below.

const express = require('express');
const router = express.Router();

const data = [
  {id: 1, title: 'Finalize project',          order: 1, completed: false, createdOn: new Date()},
  {id: 2, title: 'Book ticket to London',     order: 2, completed: false, createdOn: new Date()},
  {id: 3, title: 'Finish last article',       order: 3, completed: false, createdOn: new Date()},
  {id: 4, title: 'Get a new t-shirt',         order: 4, completed: false, createdOn: new Date()},
  {id: 5, title: 'Create dinner reservation', order: 5, completed: false, createdOn: new Date()},
];

router.get('/', function (req, res) {
  res.status(200).json(data);
});

router.get('/:id', function (req, res) {
  let found = data.find(function (item) {
    return item.id === parseInt(req.params.id);
  });

  if (found) {
    res.status(200).json(found);
  } else {
    res.sendStatus(404);
  }
});

router.post('/', function (req, res) {
  let itemIds = data.map(item => item.id);
  let orderNums = data.map(item => item.order);

  let newId = itemIds.length > 0 ? Math.max.apply(Math, itemIds) + 1 : 1;
  let newOrderNum = orderNums.length > 0 ? Math.max.apply(Math, orderNums) + 1 : 1;

  let newItem = {
    id: newId,
    title: req.body.title,
    order: newOrderNum,
    completed: false,
    createdOn: new Date()
  };

  data.push(newItem);

  res.status(201).json(newItem);
});

router.put('/:id', function (req, res) {
  let found = data.find(function (item) {
    return item.id === parseInt(req.params.id);
  });

  if (found) {
    let updated = {
      id: found.id,
      title: req.body.title,
      order: req.body.order,
      completed: req.body.completed
    };

    let targetIndex = data.indexOf(found);

    data.splice(targetIndex, 1, updated);

    res.sendStatus(204);
  } else {
    res.sendStatus(404);
  }
});

router.delete('/:id', function (req, res) {
  let found = data.find(function (item) {
    return item.id === parseInt(req.params.id);
  });

  if (found) {
    let targetIndex = data.indexOf(found);

    data.splice(targetIndex, 1);
  }

  res.sendStatus(204);
});

module.exports = router;

Short Explanation

I wanna explain shortly some points of our last codes.

First of all you must have noticed that our api works on a static data and keeps it on memory. All of our GET, POST, PUT and DELETE http methods just manipulate a json array. The purpose of this is to keep article simple and draw attention to the Web API structure.

Due to this situation our POST method has some extra logic such as calculating next item ids and order numbers.

So you can modify logic and data structures in these http methods to use a database or whatever you want.

Testing API with Postman

We have tested the GET methods of our Web API in our web browser and seen responses. But we can’t test directly POST, PUT and DELETE http methods in web browser.

If you want to test also other http methods you should use Postman or another http utility.

Now I’ll show you how to test the Web API with Postman

Before we start click here and install Postman.

When you first launch Postman after installing you’ll see start window. Close this start window by clicking close button on top right corner. Then you must see following screen.

An empty Postman request

Sending GET Request

Before sending a request to API we should start it by running npm startcommand as we do before.

After start the Web API and seeing “Server listening on…” message write localhost:3000/itemsto address bar as seen below and click Send button. You'll see todo items array as API response like below.

Sending a GET request with Postman

You can try similarly by giving an item id in request url like this localhost:3000/items/3

Sending POST Request

To sending a POST request and create a new todo item write localhost:3000/items to address bar and change HTTP verb to POST by clicking arrow at front of the address bar as seen below.

Sending a POST request with Postman

Before sending the POST request you should add request data to body of the request by clicking body tab and selecting raw and JSON as seen below.

Attaching a JSON body to POST request in Postman

Now click Send button to send POST request to the Web API. Then you must get “201 Created” http response code and seeing created item in the response body.

To see the last status of todo items send a get request to localhost:3000/itemsaddress. You must see newly created item at the end of the list.

Sending PUT Request

Sending PUT request is very similar to sending POST request.

The most obvious difference is request url should be pointed specific item like this localhost:3000/items/3

And you should choose PUT as http verb instead of POST and send all of the required data in the request body unlike POST.

For example you could send a JSON body in the PUT request as below.

An example JSON body for PUT request

{
    "title": "New title of todo item",
    "order": 3,
    "completed": false
}

When you click Send button you must get “204 No Content” http response code. You can check item you updated by sending a get request.

Sending DELETE Request

To send a DELETE request, change the request url to address a specific item id like this localhost:3000/items/3

And select DELETE as http verb and click Send button.

You must get “204 No Content” http response code as result of the DELETE operation.

Send a get request and see the last status of list.

About the DELETE Http Request

I want to say a few words about DELETE http request. You must have noticed something in our delete code. DELETE request returns “204 No Content” every situation.

Http DELETE requests are idempotent. So what that mean? If you delete a resource on server by sending DELETE request, it’s removed from the collection. And every next DELETE request on the same resource won’t change outcome. So you won’t get “404 Not Found” in the second request. Each request returns same response whether succeed or not. That’s mean idempotent operation.

Conclusion

Finally we’ve tested all http methods of our Web API.

As you can see, it works just fine.

Thanks for reading ❤

If you liked this post, share it with all of your programming buddies!

How to Create a Fake REST API Server using Node.js

How to Create a Fake REST API Server using Node.js

How to make a REST API Server using Node.js for testing your AJAX client side.

In this post, I want to show you how to create a fake REST API Server, using Node.js. This will be just a Server to test AJAX at your client side. In addition to it, it added support for CORS and request verbs like (POST, GET, DELETE, PUT).

First of all, create a folder (RESTAPI)  and create a JSON file, as shown below. I used the file mentioned in the link above for sample JSON data.

{  
   "user1" : {  
      "name" : "mahesh",  
      "password" : "password1",  
      "profession" : "teacher",  
      "id": 1  
   },  
   "user2" : {  
      "name" : "suresh",  
      "password" : "password2",  
      "profession" : "librarian",  
      "id": 2  
   },  
   "user3" : {  
      "name" : "ramesh",  
      "password" : "password3",  
      "profession" : "clerk",  
      "id": 3  
   }  
}  

From start menu, open Node.Js command prompt and change the directory, where our folder is located and type the command given below.

npm install express --save

Create a JavaScript file, add the piece of code and name it server.js.

var express = require('express');  
var app = express();  
var fs = require("fs");  
var bodyParser = require('body-parser');  
  
//enable CORS for request verbs
app.use(function(req, res, next) {  
  res.header("Access-Control-Allow-Origin", "*");  
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");  
  res.header("Access-Control-Allow-Methods","POST, GET, PUT, DELETE, OPTIONS");  
  next();  
});  
  
app.use(bodyParser.urlencoded({  
    extended: true  
}));  
  
app.use(bodyParser.json());  
  
//Handle GET method for listing all users
app.get('/listUsers', function (req, res) {  
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       console.log( data );  
       res.end( data );  
   });  
})  
  
//Handle GET method to get only one record
app.get('/:id', function (req, res) {  
   // First read existing users.  
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       users = JSON.parse( data );  
       console.log(req.params.id);  
       var user = users["user" + req.params.id]   
       console.log( user );  
       res.end( JSON.stringify(user));  
   });  
})  
  
//Handle POST method
app.post('/addUser', function (req, res) {  
   // First read existing users.  
       fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       var obj = JSON.parse('[' + data + ']' );  
       obj.push(req.body);  
       console.log(obj);  
         
       res.end( JSON.stringify(obj)  );  
   });  
})  
  
//Handle DELETE method
app.delete('/deleteUser/:id', function (req, res) {  
  
   // First read existing users.  
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       data = JSON.parse( data );  
         
       delete data["user" + req.params.id];  
         
       console.log( data );  
       res.end( JSON.stringify(data));  
   });  
})  
  
//Handle GET method
app.put('/updateUser/:id', function(req,res){  
      
    // First read existing users.  
    fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {  
       //var obj = JSON.parse('[' + data + ']' );  
       data = JSON.parse( data );  
       var arr={};  
       arr=req.body;  
         
        data["user" + req.params.id]= arr[Object.keys(arr)[0]] ; //  req.body;   //obj[Object.keys(obj)[0]]  
          
        res.end( JSON.stringify( data ));  
         
    });  
} );  
  
var server = app.listen(8081, function () {  
  
  var host = server.address().address  
  var port = server.address().port  
  
  console.log("Example app listening at http://%s:%s", host, port)  
  
})  

Notice

The parameter (data) of the request handler method is supposed to be an array of JSON objects but it didn't accept the normal array methods like (push) method, so I decided to parse it with the brackets [ ].

var obj = JSON.parse('[' + data + ']' );     

To run this Server, open node.js command prompt and run the command.

$ node server.js

Now, the Server is running and now you have a REST API Server, which supports CORS for the requests.

Here, it is listening at port 8081. To test our Server, this is the sample data for the testing purpose.

Here, it is listening at port 808. To test our Server, this is a sample data for the testing purpose.

I hope it comes in handy. Thank you for reading !

How to create a REST API with Node.js

How to create a REST API with Node.js

In this article, you'll learn the process of building REST API with Node.js from scratch.

What is REST API?

REST or RESTful stands for REpresentational State Transfer. It is an architectural style as well as an approach for communications purpose that is often used in various web services development. In simpler terms, it is an application program interface (API) which makes use of the HTTP requests to GET, PUT, POST and DELETE the data over WWW.

REST architectural style helps in leveraging the lesser use of bandwidth which makes an application more suitable for the internet. It is often regarded as the “language of the internet”. It is completely based on the resources where each and every component is regarded as a component and a single resource is accessible through a common interface using the standard HTTP method.

To understand better, let’s dive a little deeper and see how exactly does a REST API work. Basically, the REST API breaks down a transaction in order to create small modules. Now, each of these modules is used to address a specific part of the transaction. This approach provides more flexibility but requires a lot of effort to be built from the very scratch.

The main functions used in any REST based architecture are:

  • GET − Provides read-only access to a resource.
  • PUT − Creates a new resource.
  • DELETE − Removes a resource.
  • POST − Updates an existing resource or creates a new resource.

But all who claims cannot be referred to as RESTful API. In order to be regarded as a RESTful API, your application must satisfy certain constraints or principles. In the next section of this article on Building a REST API using Node.js, I will be talking about these principles in detail.

Principles of REST

Well, there are six ground principles laid down by Dr. Fielding who was the one to define the REST API design in 2000. Below are the six guiding principles of REST:

  1. Stateless
  2. Requests sent from a client to the server contains all the necessary information that is required to completely understand it. It can be a part of the URI, query-string parameters, body, or even headers. The URI is used for uniquely identifying the resource and the body holds the state of the requesting resource. Once the processing is done by the server, an appropriate response is sent back to the client through headers, status or response body.
  3. Client-Server
  4. It has a uniform interface that separates the clients from the servers. Separating the concerns helps in improving the user interface’s portability across multiple platforms as well as enhance the scalability of the server components.
  5. Uniform Interface
  • To obtain the uniformity throughout the application, REST has defined four interface constraints which are:Resource identification
  • Resource Manipulation using representations
  • Self-descriptive messages
  • Hypermedia as the engine of application state
  1. Cacheable
  2. In order to provide a better performance, the applications are often made cacheable. It is done by labeling the response from the server as cacheable or non-cacheable either implicitly or explicitly. If the response is defined as cacheable, then the client cache can reuse the response data for equivalent responses in the future. It also helps in preventing the reuse of the stale data.
  3. Layered system
  4. The layered system architecture allows an application to be more stable by limiting component behavior. This architecture enables load balancing and provides shared caches for promoting scalability. The layered architecture also helps in enhancing the application’s security as components in each layer cannot interact beyond the next immediate layer they are in.
  5. Code on demand
  6. Code on Demand is an optional constraint and is used the least. It permits a clients code or applets to be downloaded and extended via the interface to be used within the application. In essence, it simplifies the clients by creating a smart application which doesn’t rely on its own code structure.

Now that you know what is a REST API and what all you need to mind in order to deliver an efficient application, let’s dive deeper and see the process of building REST API using Node.js.

Practical Demonstration: Building REST API using Node.js

Here, we will be creating a simple CRUD REST application for Library Management using Node.js and Express.js. To build this application, you will need to install the following:

  1. Node.js
  2. Express.js
  3. Joi
  4. nodemon (Node Monitor)

In this example, I will be using the WebStorm IDE to write and execute the codes. You can use any IDE or code editor according to your choice. So, let’s get started.

First, you need to create your project directory. Next, open the command prompt and navigate to your project directory. Once there, you need to call npm using the below command:

npm init

When you hit enter, Node.js will ask you to enter some details to build the .json file such as:

Here you can define your entry point along with several other information. For this demo, I will be using script.js as an entry point. Next, we will be installing Express.js using the below command:

npm i express

Finally, I will be installing a node monitoring package called nodemon. It keeps a watch on all the files with any type of extension present in this folder. Also, with nodemon on the watch, you don’t have to restart the Node.js server each time any changes are made. nodemon will implicitly detect the changes and restart the server for you.

npm i -g nodemon

package.json

{
"name": "samplerestapi",
"version": "1.0.0",
"description": "Edureka REST API with Node.js",
"main": "script.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "Edureka",
"license": "ISC",
"dependencies": {
"express": "^4.16.4",
"joi": "^13.1.0"
}
}

script.js

const express = require('express');
const Joi = require('joi'); //used for validation
const app = express();
app.use(express.json());

const books = [
{title: 'Harry Potter', id: 1},
{title: 'Twilight', id: 2},
{title: 'Lorien Legacies', id: 3}
]

//READ Request Handlers
app.get('/', (req, res) => {
res.send('Welcome to Edurekas REST API with Node.js Tutorial!!');
});

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

app.get('/api/books/:id', (req, res) => {
const book = books.find(c => c.id === parseInt(req.params.id));

if (!book) res.status(404).send('<h2 style="font-family: Malgun Gothic; color: darkred;">Ooops... Cant find what you are looking for!</h2>');
res.send(book);
});

//CREATE Request Handler
app.post('/api/books', (req, res)=> {

const { error } = validateBook(req.body);
if (error){
res.status(400).send(error.details[0].message)
return;
}
const book = {
id: books.length + 1,
title: req.body.title
};
books.push(book);
res.send(book);
});

//UPDATE Request Handler
app.put('/api/books/:id', (req, res) => {
const book = books.find(c=> c.id === parseInt(req.params.id));
if (!book) res.status(404).send('<h2 style="font-family: Malgun Gothic; color: darkred;">Not Found!! </h2>');

const { error } = validateBook(req.body);
if (error){
res.status(400).send(error.details[0].message);
return;
}

book.title = req.body.title;
res.send(book);
});

//DELETE Request Handler
app.delete('/api/books/:id', (req, res) => {

const book = books.find( c=> c.id === parseInt(req.params.id));
if(!book) res.status(404).send('<h2 style="font-family: Malgun Gothic; color: darkred;"> Not Found!! </h2>');

const index = books.indexOf(book);
books.splice(index,1);

res.send(book);
});

function validateBook(book) {
const schema = {
title: Joi.string().min(3).required()
};
return Joi.validate(book, schema);

}

//PORT ENVIRONMENT VARIABLE
const port = process.env.PORT || 8080;
app.listen(port, () => console.log(`Listening on port ${port}..`));

Now, the next step is to check whether the handlers are working properly or not. For that, we will use a Chrome extension called Postman. To install Postman you can visit hereand click on ‘Add to Chrome’.

Once you have successfully installed Postman, open it and start testing your application. So, let’s start off by testing our GET method. Now, in order to do that you need to select GET from the drop-down list, type in the defined URI and hit send. If your code is working fine, then you will see the list of all the books which we have added manually in our code. In the below picture, you can see how my result looks like.

Now, let’s try adding a new book to our inventory list. For that, select ‘POST’ from the drop-down list and type in the defined URI for the POST method. Now, click on ‘Body’, select ‘raw’ and move on to select ‘JSON’ from the drop-down list as depicted in the below image. Now, in the text area, type in the title of your book as shown and hit send.

If your POST method is working fine, your response body will contain the book title along with the book id. Now, let’s try to update the book title. Currently, my book title is “Angels and Demons” which I will be updating to “Angels & Demons”. So, to update the data, you need to first select ‘PUT’ from the drop-down table and enter the PUT request’s URI along with the book id you wish to update. Next in the ‘Body’, type in the new book title and hit enter.


This will give you a response with the book id and updated book title.

Finally, let’s send a ‘DELETE’ request to delete an existing record. For that select DELETE from the drop-down list and type in the URI of the delete request handler along with the book details, you want to remove and hit enter. If your transaction is successful, you will see the complete details of the entry you have removed in the response body.

Now, let’s send a GET request for our final list of books.


As you can see from the above screenshot, the response body contains a total of three books with the book id 3 missing as we have already deleted that entry.