Building a RESTful API with Node.js and Express

In today's digital age, where data flows like a river and web and mobile applications dominate our daily lives, the ability to create robust and efficient RESTful APIs is nothing short of essential. These APIs serve as the foundation upon which modern web services are built, allowing applications to communicate, share data, and deliver functionality seamlessly. Whether you're a seasoned developer looking to expand your skill set or a newcomer eager to dive into API development, this comprehensive guide is designed to empower you with the knowledge and practical skills needed to create your very own RESTful API.

Why RESTful API?

RESTful APIs (Representational State Transfer) are the backbone of web development, providing a standardized way for different software systems to interact with each other over the internet. They enable everything from social media interactions and e-commerce transactions to mobile app updates and IoT device control. Understanding how to design, build, and deploy RESTful APIs is a must for developers, as it opens up a world of possibilities for creating dynamic, data-driven applications.

Key Topics Covered

Our journey includes :

  • Setting up a Node.js development environment.

  • Creating routes and handling HTTP requests.

  • Implementing data storage with MongoDB.

  • Incorporating authentication and security measures.

  • Ensuring thorough testing and documentation of your API.

So, are you ready to embark on this exciting journey of API development? Let's dive in and start building a RESTful API with Node.js and Express that will empower your applications to connect, communicate, and conquer the digital landscape.

Setting up a Node.js environment

Certainly! Here are step-by-step instructions for setting up a Node.js project for creating an API in Visual Studio Code:

  1. Create a Project Folder:

Open a terminal and navigate to the directory where you want to create your Node.js project. Use the mkdir command to create a new folder. For example:

mkdir FriendsAPI
  1. Navigate to Folder

Change your current directory to the newly created project folder using the cd command. Write code . a command in the terminal to open the folder in the code editor.

cd FriendsAPI
  1. Initialize a Node.js Project:

To initialize a new Node.js project, you can use the npm init command. This command will guide you through creating a package.json file, which contains project metadata and dependencies. Run the following command:

npm init -y
  1. Install some dependencies:
    To make things flawless and easy we are going to use some dependencies for our tutorial
npm i mongoose express nodemon dotenv

Here is the use of these dependencies as follows:

  1. Express will be used for the middleware to create various CRUD endpoints.

  2. Mongoose for managing data in MongoDB using various queries.

  3. Nodemon to restart our server every time we save our file.

  4. Dotenv to manage a .env file.

Now let's jump into the actual things that are necessary which is starting an express server and creating a simple endpoint first

  1. In the terminal write touch index.js to create an index.js file in the current directory.

  2. In the index.js file create a simple endpoint

    ```javascript const express = require('express'); const app = express(); const port = 3000; app.use(express.json());

    app.get('/', (req, res) => { res.send('Your are my friend'); });

app.listen(port, () => { console.log(Friends API is running on port ${port}); });


    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1694802315801/c9ffd0e2-51bf-41b4-b11a-e48a1067c9d1.png align="center")

3. To prevent again and again doing `node index.js` in the terminal we will use nodemon which restarts the node.js server to save time to do this just go to package.json and in that in the script section write the following:

    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1694802721828/35ea20d7-2d6b-4fb6-b539-9eca01d51750.png align="center")

    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1694802672422/58674005-4003-432e-8529-41a7e3197929.png align="center")


## Setting up MongoDB Atlas

We can use MongoDB Compass but to show you the cloud side of MongoDB I am considering the MongoDB Atlas for this tutorial.

Go to the MongoDB Atlas website then with a simple sign-up you are ready to use the power of the Cloud database.

Now we have to make a Start with New Project and we will name here this project **Friends\_DB** for convenience.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695059543050/ca10af61-738a-4f19-ba7e-19fdb542b6f0.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695059571515/6800bd78-7443-4cb4-aa0d-73b614fcfab0.png align="center")

Now choose the cloud database deployment model, if you are working on a personal project then you can choose the Free **M0** Plan and if it is a professional project then you can go for paid plans too.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695059755679/88959fba-0d36-462a-baef-b292fadb1c66.png align="center")

Now you have to set credentials such as username and password to connect the node.js application from the database from our Code editor.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695059985612/6d0640f7-ddd5-4afc-bf27-4653174999cb.png align="center")

Just remember to save the ***Password*** for the connection.

Now Connect the database with **VSCode** by clicking on **connect** and then choosing the option from a bunch of options.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695060209076/45acd98b-ed5c-42e9-beee-9c6d44a60c20.png align="center")

Copy the MongoDB URI and paste in the environment variable file in the VSCode with the name **.env**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695060405405/309b60ee-255b-4518-b08c-291d05d48aed.png align="center")

.env file is an environment variable file used to protect API Keys, Passwords, port numbers, and many more credentials to avoid direct use in the code.

Now let's import this credential in the script file using **dotenv** dependency.

```javascript
require('dotenv').config();

const connect_DB = process.env.MONG_URI

we are storing the credential in the connect_DB variable.

Now let's connect the database to our node.js server.

const mongoose=require('mongoose');
mongoose.connect(connect_DB);
const database = mongoose.connection;
database.on('error', (error) => {
    console.log(error)
})

database.once('connected', () => {
    console.log('Database Connected');
})

Here, database.on means it will connect to the database and throws any error if the connection fails. And database.once means it will run only one time. If it is successful, it will show a message that says Database Connected.

How to Create Our Routes for the Endpoints

Create a Folder named routes and in that folder make one script file called routes.js which contains all the endpoints for our API.

mkdir route
cd route
touch routes.js

Now, let's write our endpoints here in this routes file. We will have five routes for the following actions:

  1. Posting data to the Database.

  2. Getting all the data from the Database.

  3. Getting data based on the ID.

  4. Updating data based on the ID.

  5. Deleting data based on the ID.

The basic structure for our routes are as follows:

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

router.get('/friends',(req,res)=>{
   res.send('get all Friend with this Endpoint');
})

router.post('/friends',(req,res)=>{
  res.send('Make Friend with this Endpoint');
})

router.get('/friends/:id',(req,res)=>{
   res.send('Fet specific friend with this Endpoint');
})

router.put('/friends/:id',(req,res)=>{
   res.send('Update Friend Info with this Endpoint');
})

router.delete('/friends/:id',(req,res)=>{
   res.send('Remove Friend from your list with this Endpoint');
});

module.exports = router;

Now we have framed a basic body for our API routes so let's check the API endpoints in the Postman if you haven't used the Postman yet then download the Postman.

Before checking the API directly let's jump into the index.js file and import the routes and use it in the basic express server that we made earlier.

const friendsRoute=require('./route/routes.js');

Above we have just imported the routes in the friendsRoute variable.

const app = express();
const port = 3000;
app.use('/api', friendsRoute);

By using app.use('/api', friendRoutes);, you are specifying that all routes defined in friendRoutes should be accessible under the /api prefix. For example, the "GET /friends" route defined in route.js will be accessible at http://localhost:3000/api/friends.

Now jump onto the screen of Postman for API Testing.

We utilize tools such as Postman due to the inherent limitations of web browsers. While web browsers excel at making GET requests to retrieve information from web servers, they lack the native capability to perform more advanced HTTP operations such as POST or DELETE requests. To bridge this gap and facilitate comprehensive API testing and interaction, we turn to dedicated API testing tools like Postman.

GET Request

POST Request

So you might be thinking that from where we will get the /:id in the endpoint.So this we will get from the res.body.

How to Create the Model

Now, let's create a Model that will define our database structure.

Create a folder called models and inside, a file called model

.js.

Here is the friends model as follows which have name,age,friends,friends_rating as property.

const mongoose = require('mongoose');

// Define the friend schema
const friendSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  age: {
    type: Number,
    required: true
  },
  friends: [{
    type: String // Assuming friends are represented as an array of strings (friend names)
  }],
  friends_rating: {
    type: Number,
    min: 0,  // Minimum rating value
    max: 5   // Maximum rating value
  }
});

// Create and export the Friend model
const Friend = mongoose.model('Friend', friendSchema);

module.exports = Friend;

Now let's import the model inside our route file.

const Model=require('../models/model.js');

CRUD Operations

Let's implement the Create, Read, Update, and Delete Operations

Creating a new Friend in the Database:

Let's create the data body to post using the model we just created.


// Create a new friend
router.post('/friends', async (req, res) => {
  try {
    const { name, age, friends, friends_rating } = req.body; //Object destructuring


    const newFriend = new Friend({
      name,
      age,
      friends,
      friends_rating
    });

    // Save the new friend to the database
    const savedFriend = await newFriend.save();

    res.status(201).json(savedFriend);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

In the above code the name, age, friends, and friends_rating properties are directly mapped by extracting it from req.body object. This is called Object destructuring.

The thing is re.body we will get from a frontend Client like React or Angular App or Postman in this case.

Get all Friends List from the Database

Let's get all our friends from the Database

router.get('/friends', async (req, res) => {
  try {
    const allFriends = await Friend.find();
    res.status(200).json(allFriends);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Friend.find() is used to get all friends from the database.

Get Specific Friend's Data

Using id we can get the data of specific data

router.get('/friends/:id', async (req, res) => {
  try {
    const friendId = req.params.id;
    const friend = await Friend.findById(friendId);

    if (!friend) {
      return res.status(404).json({ error: 'Friend not found.' });
    }

    res.status(200).json(friend);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

In Express.js, req.params.id is used to access route parameters from the URL. Specifically, it allows you to retrieve the value of a route parameter named "id" from the URL. Suppose For instance, if you make a GET request to "/users/123", req.params.id will be equal to "123" in the route handler, and you can use it to look up user data with the ID of 123 from your data source or database.

Update the Friend's Information

This is kind of tricky out of all the above parts but still we will make it easy for you

router.put('/friends/:id', async (req, res) => {
  try {
    const friendId = req.params.id;
    const updatedData = req.body;

    const updatedFriend = await Friend.findByIdAndUpdate(friendId, updatedData, {
      new: true, // Return the updated document
      runValidators: true // Run model validations
    });

    if (!updatedFriend) {
      return res.status(404).json({ error: 'Friend not found.' });
    }

    res.status(200).json(updatedFriend);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

To update specific data, we start by accessing it using the unique ID provided in the URL (accessible via req.params.id). Once we have access to the data, we make the desired updates. In our case, the updated information is stored in the updatedData variable.

To apply these updates to our database, we use a concise and efficient Mongoose method called findByIdAndUpdate. This method takes three main parameters:

  1. friendId: The unique identifier of the friend we want to update.

  2. updatedData: The new data that we want to replace the existing data with.

  3. An options object with two properties:

    • new: true: This instructs Mongoose to return the updated document after the update is performed.

    • runValidators: true: This tells Mongoose to run any model-level validation checks on the updated data.

By utilizing findByIdAndUpdate, we efficiently locate and update the specific friend's data, ensuring that the new information adheres to our defined model's validation rules. This approach streamlines the update process and guarantees data consistency in our application.

Delete the Friend from the Database

Removing friend from the database is easy

// Remove a friend by ID
router.delete('/friends/:id', async (req, res) => {
  try {
    const friendId = req.params.id;
    const deletedFriend = await Friend.findByIdAndRemove(friendId);

    if (!deletedFriend) {
      return res.status(404).json({ error: 'Friend not found.' });
    }

    res.status(204).send(); // 204 status means No Content
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Using the id of the friend we remove the friend using .findByIdAndRemove(id)

Now if we test this we will get the following:

Created a Friend named John and now make some more Friends by yourself

Now let's find a friend with a specific id in the database

Now Let's Update the Friends Information using the id

Let's list all the friends we have in database

Now Let's Delete John from Friend's List

Thank You for Reading!

Thank you for joining us on this journey of discovery. Your time and attention mean the world to us.

We hope you found this blog post informative, insightful, and inspiring. Your support is what drives us to continue sharing valuable content with you.

Did you find this article valuable?

Support Vishal Sharma by becoming a sponsor. Any amount is appreciated!