How to build a simple RESTful API with Node.js and Express: Managing Tasks

How to build a simple RESTful API with Node.js and Express: Managing Tasks

Introduction:

In Understanding a RESTful API for software integration, we talked about the principles, and best practices, in this article we are going to take it up a notch by building a restful API to manage tasks.

The Project:

We are going to build an API that allows users to:

  1. Create Tasks: Add tasks to a server

  2. Get a Task: Retrieve a specific task and its details

  3. Update a Task: Make changes to a task

  4. Delete a Task: Remove a task from a server

  5. List Tasks: Get a list of all tasks

Tools and Technologies:

For this project, we will be using some tools:

Programming Language: Node.js with Express framework(a good way to learn how to work with Node and Express)

Data Storage: MongoDB.

Data Format: JSON for data formart & serialization

API Documentation: Swagger for API documentation

API Testing: Postman for API testing.

Implementation and Steps:

Follow these steps and start building(Make sure you create a directory for your project):

  1. Setting up the project: This is the first step, and to do this it simply means initializing our Node.js project using: npm init, which will create a package.json file, after pressing the enter key and finally typing yes.

     npm init
    

    After this install the Express.js, mongo, and body-parser(to parse incoming requests majorly as JSON) dependency: npm install express.

     npm install express mongoose body-parser
    

    Create a new file in your project directory called server.js to set up our Express server.

  2. Define Task Data Model:

    Next, create a Models directory and then create a file called task.js to define the Task data model using Mongoose (“Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It helps developers to model their data, define the schema for documents inside a collection, and manage relationships between data” - Source Mongodb).

    For this guide, we are using a remote Mongo database.

  3. Create Task Routes:

    Create a routes directory, and create a file in it called taskRoutes.js to define our APIs/Routes to perform the various functions.

    Create task:

     // Create a new task
     router.post('/v1/tasks', async (req, res) => {
       const task = new Task(req.body);
       try {
         await task.save();
         res.status(201).send(task);
       } catch (error) {
         res.status(400).send(error);
       }
     });
    

    Get all tasks and get tasks by ID:

     // Get all tasks
     router.get('/v1/tasks', async (req, res) => {
       try {
         const tasks = await Task.find();
         res.send(tasks);
       } catch (error) {
         res.status(500).send(error);
       }
     });
    
     // Get a task by ID
     router.get('/v1/tasks/:id', async (req, res) => {
       const _id = req.params.id;
       try {
         const task = await Task.findById(_id);
         if (!task) {
           return res.status(404).send();
         }
         res.send(task);
       } catch (error) {
         res.status(500).send(error);
       }
     });
    

    Update and Delete a task by ID:

     // Update a task by ID
     router.patch('/v1/tasks/:id', async (req, res) => {
       const updates = Object.keys(req.body);
       const allowedUpdates = ['description', 'completed'];
       const isValidOperation = updates.every((update) =>
         allowedUpdates.includes(update)
       );
    
       if (!isValidOperation) {
         return res.status(400).send({ error: 'Invalid updates!' });
       }
    
       try {
         const task = await Task.findByIdAndUpdate(req.params.id, req.body, {
           new: true,
           runValidators: true,
         });
    
         if (!task) {
           return res.status(404).send();
         }
    
         res.send(task);
       } catch (error) {
         res.status(400).send(error);
       }
     });
    
     // Delete a task by ID
     router.delete('/v1/tasks/:id', async (req, res) => {
       try {
         const task = await Task.findByIdAndDelete(req.params.id);
    
         if (!task) {
           return res.status(404).send();
         }
    
         res.send(task);
       } catch (error) {
         res.status(500).send(error);
       }
     });
    

    It should look like this:

  4. Middleware and Documentation:

Here we will begin to parse our JSON in server.js.

const taskRoutes = require('./routes/taskRoutes');

app.use(express.json()); // Parse JSON requests

app.use(taskRoutes); // Use the task router

Add Swagger for API Documentation:

npm install swagger-jsdoc swagger-ui-express

After installation, create a swagger.js file to configure Swagger

Then update taskRoutes.js to include swagger documentation:

const swaggerJSDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

// ... (taskRoute code)

const options = {
  swaggerDefinition: {
    openapi: '3.0.0',
    info: {
      title: 'Task Manager API',
      version: '1.0.0',
    },
  },
  apis: ['./routes/*.js'], // Path to your routes files
};

const swaggerSpec = swaggerJSDoc(options);

router.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
  1. Start the server and Test APIs

    We’ll start the Express server:

     node server.js
    

    Then we’ll use Postman to test the API endpoints:

    • Create tasks using POST: /v1/tasks

    • List all tasks by using GET: /v1/tasks

    • List a task by using GET and the ID: /v1/tasks/:id

    • Update a task by using PUT: /v1/tasks/:id

    • Delete a task by using DELETE: /v1/tasks/id

      POST method with a response from the server

GET method with a list of the tasks: