In this article, ill share how I build a Todo list RESTfull Web API with Complete CRUD functionality using Node.js and Express.
First let's understand what is REST, API, CRUD, NODE.js, and express are.
REST API
A REST stands for Representational State Transfer and API stands for an application programming interface. REST is an architectural style and approach to communications often used in web services development.
NODE.js
Node.js is a server-side platform built on Google Chrome's JavaScript Engine (V8 Engine) which is created for easily building fast and scalable network applications.
Express
Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
CRUD
CRUD is simply an acronym used to refer to four basic operations that can be performed on database applications:
- Create
- Read
- Update
- Delete
Before start
Install Node.js and npm Package Manager To check whether Node.js is already installed on your computer, open your terminal and run the command.
node -v
If you see your Node.js version it's installed you are good to go otherwise you can follow this Official documentation
for Linux just use :
sudo apt-get install -y nodejs
CREATE A PROJECT:
Create a folder on your Desktop and call it whatever you like. Now, go ahead and open that folder in VS Code.
Fire up your terminal in VS Code by clicking Ctrl + ~
and run the following command to initialize a project and create important files and folders:
npm init
touch app.js
touch .env
mkdir controllers
mkdir routes
npm install express cors
npm install --save-dev nodemon prettier
Create server
Now let's start working on the app.js file this will be the entry point of our application now import express and cors packages and create an express app.
//Import all the necessary packages
const express = require("express");
const cors = require("cors");
//Creating and express app
const app = express();
Set host and Port for your server
//PORT and host
const host = "localhost";
const PORT = 8000;
And important middleware for our application like express.json and cors
//CORS middlware to allow cross origin resources sharing
app.use(cors());
//Middleware to convert our request data into JSON format
app.use(express.json());
To check whether API is working perfectly or not we can add a simple route handle
//Welcome to API response
app.get("/", (req, res) => {
res.send("Hello There API is now Working");
});
You might be thinking what is this get thing will its a HTTP method in simple
In a RESTful API, endpoints define the structure and usage with the GET
, POST
, PUT
, and DELETE
HTTP methods. You must organize these methods logically.
Now everything is in its place we can start the server to listen on our host and port and log something to see how it's working
//App listening on PORT 8000
app.listen(PORT, () => {
console.log(`Server is now Started on http://${host}:${PORT}`);
});
let's add a script to develop and start our server to do that add script with the command you want to run in the package.json file, we are using nodemon to develop our application because it helps users to restart our server on the go when we add something new to the code and node for starting the server for the production
"scripts": {
"dev": "nodemon app.js",
"start": "node app.js"
}
start the server by entering a command on the terminal
➡️ npm run dev
> rest-api@1.0.0 dev
> nodemon app.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node app.js`
Server is now Started on http://localhost:8000
To weather the API is working fine we can use Postman and make a GET
request to the address http://localhost:8000
Here you can see we successfully get our log message.
Create Routes
Now we know our server is working fine let's start working on the routes folder inside the routes folder create a new file name todo.routes.js and define all the routes inside the file
- Get all the Todos
- Get one Todo by Id
- Post new Todo
- Update any Todo by Id
- Delete any Todo by Id
and also export all these routes
// Define Router
const express = require("express");
const Router = express.Router();
//GET all the tods
Router.get("/");
//GET one Todo
Router.get("/:id");
//CREATE one todo
Router.post("/");
//UPDATE one todo
Router.put("/:id");
//DELETE one todo
Router.delete("/:id");
//Export Router
module.exports = Router;
Sending GET Request
Now we can start working on the main core logic of our application inside the controller folder and make a new file todo.controller.js. make an array of name Todo or anything you like and create a sample data inside it
//Sample Todo objects
const Todos = [
{
id: 1,
title: "Study",
completed: false,
createdOn: new Date(),
},
{
id: 2,
title: "Coding",
completed: true,
createdOn: new Date(),
},
];
To make GET
endpoints work we will make two functions call getTodos and getTodo.
getTodos will simply return all the JSON data we have in the Array Todos,
getTodo will first find the item in the array using the req.params.id
and if we successfully found it we can return it if now we can send status code 404 which mean not found
//Get all todos function
const getTodos = (req, res) => {
res.status(201).json(Todos);
};
//Get one todo function
const getTodo = (req, res) => {
let found = Todos.find(function (item) {
return item.id === parseInt(req.params.id);
});
if (found) {
res.status(200).json(found);
} else {
res.sendStatus(404);
}
};
Sending POST Request
Now lets work on POST
we will create a new function that will take data from req.body
and push it to the Todos array with a new Id
//Create one todo function
const postTodo = (req, res) => {
let itemIds = Todos.map((item) => item.id);
let newId = itemIds.length > 0 ? Math.max(...itemIds) + 1 : 1;
let newItem = {
id: newId,
title: req.body.title,
completed: false,
createdOn: new Date(),
};
Todos.push(newItem);
res.status(201).json(newItem);
};
Sending PUT Request
Now let's work on updating the Task we will create a new function that will take data from req.body
and we can find that element in Todos with the id we got from req.params.
and simply replace it using a splice method .
And you should choose PUT
as HTTP verb instead of POST
and send all of the required data in the request body unlike POST
.
//Update one todo function
const putTodo = (req, res) => {
let found = Todos.find((item) => {
return item.id == parseInt(req.params.id);
});
if (found) {
let updated = {
id: found.id,
title: req.body.title,
completed: req.body.completed,
createdOn: new Date(),
};
let targetIndex = Todos.indexOf(found);
Todos.splice(targetIndex, 1, updated);
res.sendStatus(204);
} else {
res.sendStatus(404);
}
};
Sending DELETE Request
Now we are only left with the delete function and we can use the same logic we used before just here we will just remove the element when we found no replace.
//Delete One todo function
const deleteTodo = (req, res) => {
let found = Todos.find((item) => {
return item.id == parseInt(req.params.id);
});
if (found) {
let targetIndex = Todos.indexOf(found);
Todos.splice(targetIndex, 1);
}
res.sendStatus(204);
};
We are done with all the functions lets export all the functions now so we can use them in routes
//Export Functions
module.exports = {
getTodos,
getTodo,
postTodo,
putTodo,
deleteTodo,
};
Set controller at each endpoint
now we can add these function to the router's endpoint so it work whenever we hit that endpoint.
// Define Router
const express = require("express");
const Router = express.Router();
//Imorting all the controllers
const TodoController = require("../controllers/Todo.controller");
//GET all the tods
Router.get("/", TodoController.getTodos);
//GET one Todo
Router.get("/:id", TodoController.getTodo);
//CREATE one todo
Router.post("/", TodoController.postTodo);
//UPDATE one todo
Router.put("/:id", TodoController.putTodo);
//DELETE one todo
Router.delete("/:id", TodoController.deleteTodo);
//Export Router
module.exports = Router;
Now we are done with the coding part let's test this project and all the functionality using Postman
Now you all must have noticed that our API works on static data and keeps it in memory. All of our GET
, POST
, PUT
, and DELETE
HTTP methods just manipulate a JSON
array.
So you can modify logic and data structures in these HTTP methods to use a database or whatever you want.
You can find the source code of this Web API at this github repository.
As you can see, it works just fine.
Thank you for your time and patience.