DEV Community

Cover image for Build a simple Node.js RESTful API
Youssef Allali
Youssef Allali

Posted on • Updated on

Build a simple Node.js RESTful API

Table Of Contents

What is REST?

REST is an acronym for Representational State Transfer and it is a software architectural style which uses a subset of HTTP
RESTful APIs relies on HTTP verbs to perform four operations :
The GET (to read a resource), POST (to create and/or update a resource), and DELETE (to delete a resource)
RESTful APIs are defined with the following aspects :

  • A base URI, such as http://api.example.com/;
  • Standard HTTP methods (e.g., GET, POST, PUT, and DELETE);
  • Media types, such as application/json.

In this tutorial, we will learn how to create a RESTful API using Node.js.

Prerequisites

In order to follow along with this tutorial you will need

  • A Node.js environnement installed on your machine;
  • A text editor program or IDE (VS Code for example);
  • A mongoDB instance (here in this tutorial, we will be using the cloud database MongoDB Atals).
  • An API Client such as Postman to help us make HTTP requests and test our API server.

To avoid running into any compatibility issues, I will list the versions of programs and tools used in this tutorial :

Tool Version How to check
Node.js v14.16.1 node -v
MongoDB Node.js driver 3.6 or later
express npm module ^4.17.1 npm list express
mongoose npm module ^6.0.10 npm list mongoose

Set up the workspace

Start the project

In this tutorial, we will be creating a todo list application that will let us create, read, update and delete tasks.

Before we begin, make sure you have Node.js installed, mongoDB Atlas instance working and Postman ready for the testing.

Now, open a terminal window (or CMD, on Windows) in a preferred location or use the following command to create a folder and set it as a workspace:

$ mkdir ./todo-list-api
Enter fullscreen mode Exit fullscreen mode
$ cd ./todo-list-api
Enter fullscreen mode Exit fullscreen mode

Now, it's time to start our application by typing the following command:

$ npm init -y
Enter fullscreen mode Exit fullscreen mode

What it basically does is create a file named package.json that contains all the information about our project and its dependencies.

the -y parameter lets me skip filling informations about my project since I could modify these later in the package.json file.

Create necessary folders and files

Now, let's create the file that will contain our server script, we'll be naming it index.js since that's the default name (other conventional names can be app.js or server.js).

In the command line, type the command that will create a new empty file:

$ touch ./index.js
Enter fullscreen mode Exit fullscreen mode

Next, let's add some folders and files via the following commands:

Create 3 separate folders "models", "routes", and "controllers" using the command $ mkdir controllers models routes

Create the empty files "controller.js", "routes.js" and "model.js" inside their respective folders "controller", "routes", and "model" $ touch ./controllers/controller.js ./models/model.js ./routes/routes.js

Set up the database

Now that we have our server ready, let's set up a database.

  1. Install mongoose module

mongoose will be used to manage our MongoDB Atlas instance.

$ npm install mongoose --save
Enter fullscreen mode Exit fullscreen mode
  1. Define a schema

Open the file "model.js" and type the following code and then save it.

// model.js
const mongoose = require('mongoose');

const taskSchema = new mongoose.Schema({
  name: {
    type: String,
    required: 'Enter the name of the task'
  },
  date_created: {
    type: Date,
    default: Date.now
  },
  status: {
    type: [{
      type: String,
      enum: ['pending', 'ongoing', 'completed']
    }],
    default: ['pending']
  }
});

module.exports = mongoose.model('Tasks', taskSchema);
Enter fullscreen mode Exit fullscreen mode

In the code above, we imported the mongoose module into our file and we created a model that defines the structure of our mongoDB collection.

Set up the routes

In Express, routing instructs the sever on how to respond to client request for a specific endpoint (URI) and a specific HTTP request method.

To do this, open the file "routes.js" and type the following code and then save it.

// routes.js
module.exports = (app) => {
  const todoList = require('../controllers/controller.js');

  app.route('/tasks')
    .get(todoList.listTasks)
    .post(todoList.createTask);

  app.route('/tasks/:taskId')
    .get(todoList.readTask)
    .put(todoList.updateTask)
    .delete(todoList.deleteTask);
};
Enter fullscreen mode Exit fullscreen mode

In the code above, we defined two basic routes : "/tasks" and "/tasks/:taskId" with different methods; "/tasks" has the methods "GET" and "POST", while "/tasks/:taskId" has "GET", "PUT" and "DELETE".
As you can see, we also required the controller so each of the routes methods can call its respective handler function.

Set up the controller

open the file "controller.js" and type the following code and then save it.

// controller.js
const mongoose = require('mongoose');
const task = mongoose.model('Tasks');

exports.listTasks = (req, res) => {
  task.find({}, (err, task) => {
    if (err)
      res.send(err);
    res.json(task);
  });
};

exports.createTask = (req, res) => {
  const new_task = new task(req.body);
  new_task.save((err, task) => {
    if (err)
      res.send(err);
    res.json(task);
  });
};

exports.readTask = (req, res) => {
  task.findById(req.params.taskId, (err, task) => {
    if (err)
      res.send(err);
    res.json(task);
  });
};

exports.updateTask = (req, res) => {
  task.findOneAndUpdate({_id: req.params.taskId}, req.body, {new: true}, (err, task) => {
    if (err)
      res.send(err);
    res.json(task);
  });
};

exports.deleteTask = (req, res) => {
  task.remove({
    _id: req.params.taskId
  }, (err, task) => {
    if (err)
      res.send(err);
    res.json({ message: 'Task deleted' });
  });
};
Enter fullscreen mode Exit fullscreen mode

In the code above, we defined 5 different functions for different actions:

  • listTasks lists our tasks;
  • createTask creates a new task;
  • readTask reads the content of a task;
  • updateTask updates the content of a task;
  • deleteTask deletes a task.

Each of these functions is exported in order to be used in our routes.

Note that each of these functions uses different mongoose methods such as find, findById, save, findOneAndUpdate and deleteOne.

Set up the server

In this section, we will be connecting our controller.js, database, the created models, body parser and the routes together and at the end, we will run our server and test it.

  1. Install express module

Express will be used to create the server

$ npm install express --save
Enter fullscreen mode Exit fullscreen mode
  1. Start the server

Open the file "index.js" and follow the steps.

Essentially, what we will be doing is

  • Connect our database by adding a url to the mongoose instance connection (you can learn how to set up one by following this article);
  • Load the created model - task;
  • Register our created routes in the server.

Now, type the following code inside the file index.js and save it.
Note : Don't forget to replace the string in connectionUrl variable with your Atlas connection string.

// index.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const mongoose = require('mongoose');
const task = require('./models/model.js');

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// mongoose instance connection url connection
mongoose.Promise = global.Promise;
// Replace the following with your Atlas connection string                                                                                                                                        
const connectionUrl = "mongodb+srv://<username>:<password>@<clusterName>.mongodb.net/<databaseName>?retryWrites=true&w=majority";
mongoose.connect(connectionUrl, { 
    useNewUrlParser: true,
    useUnifiedTopology: true 
  }); 

//import routes
const routes = require('./routes/routes.js'); 

//register the route
routes(app);

app.listen(port, ()=> {
  console.log(`RESTful API server running on ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Now, back to the terminal and type $ node ./index.js and if everything is fine, you'll see the message "RESTful API server running on 3000" printed to the console.

Test the API

Now that everything is connected, let’s test some of our routes with the the registered methods.

Launch Postman or use the web-based version (you'll need to set up an account, it's free).

In Postman, we will test our routes by making requests to their respective endpoints

Since there are no tasks nor tasklists in our database yet, get requests will return an empty array ([]) from the server. So the first thing we can do is create a task.

Create a task

In order to create a new task, let's make a POST request to the following http://localhost:3000/tasks

Create task in Postman

if you can't use Postman for some reason, you can always use the command line tool "curl".

$ curl --data-urlencode 'name=Do homework' http://localhost:3000/tasks
Enter fullscreen mode Exit fullscreen mode

Delete a task

Now let's try to delete the task we have just created, in order to do that, let's make a DELETE request to the following http://localhost:3000/tasks/<taskId>
Note that we have to replace the :taskId placeholder with the task identified _id we received from the last request.

Delete task in Postman

Again, if you can't use Postman, use the command line tool "curl".

$ curl -X DELETE "http://localhost/<taskId>"
Enter fullscreen mode Exit fullscreen mode

Conclusion

Congrats! you made a functioning RESTful API.
You may find the full code for this tutorial in this Github Repository.

Final words

Don't hesitate to leave any questions you may have for me in the comments. I'll be pleased to reply and subscribe for more interesting content like this one.

Top comments (0)