Building a REST API with Node.js and Express: A Step-by-Step Guide
In this blog post, we'll explore how to build a REST API using Node.js and Express. We'll cover the basics of Node.js, set up our development environment, and walk through creating and managing API endpoints.
What is Node.js?
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It allows developers to use JavaScript to write server-side code, enabling the creation of scalable network applications.
What Can Node.js Do?
Server-side scripting
Command-line tools
Real-time applications (e.g., chat applications)
APIs for database interactions
Installation of Node.js
Visit the Node.js website.
Download and install the LTS (Long Term Support) version for your operating system.
Verify the installation by running:
node -v npm -v
What is NPM?
NPM (Node Package Manager) is a package manager for JavaScript. It comes bundled with Node.js and allows you to install libraries and dependencies for your project.
Install Postman
Postman is a popular tool for testing APIs.
Visit the Postman website.
Download and install the application for your operating system.
Create a free account to save and manage your requests.
Get a Suitable IDE for Development
Visual Studio Code (VS Code)
WebStorm
Atom
For this tutorial, we recommend VS Code.
Start with Development - Building a Book Management API with Node.js and Express
Step 1: Create a New Project
Open your terminal and create a new project directory:
mkdir book-api cd book-api
Initialize a new Node.js project:
npm init -y
Step 2: Create package.json
package.json
is the configuration file for your Node.js project. It contains metadata about your project and its dependencies.
Step 3: Install Express
Express is a minimal and flexible Node.js web application framework.
npm install express
Step 4: What is Express?
Express provides a robust set of features for web and mobile applications, including routing, middleware, and more.
Step 5: Install JOI
JOI is a powerful schema description language and data validator for JavaScript.
npm install joi
Step 6: What is JOI?
JOI allows you to create schemas to validate JavaScript objects in a simple and readable way.
Creating Application File
Step 7: Create app.js
Create an app.js
file in your project directory:
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Creating READ Request Handlers
Step 8: Define Your Data
Create a simple in-memory data store:
const books = [
{ id: 1, title: '1984', author: 'George Orwell', year: 1949 },
{ id: 2, title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960 }
];
Step 9: Create GET Request Handlers
Add the following code to handle GET requests:
app.get('/api/books', (req, res) => {
res.send(books);
});
app.get('/api/books/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).send('Book not found');
res.send(book);
});
Install Nodemon
Nodemon is a utility that monitors for changes in your source code and automatically restarts your server.
Nodemon increases productivity by automatically restarting the server whenever you make changes to your files.
npm install -g nodemon
Step 11: Handling HTTP Requests
Define the port number and create request handlers:
const port = process.env.PORT || 3000;
Creating a Function to Validate Data
Step 12: Validate Data with JOI
Define a validation schema and create a function to validate data:
const Joi = require('joi');
const validateBook = (book) => {
const schema = Joi.object({
title: Joi.string().min(3).required(),
author: Joi.string().min(3).required(),
year: Joi.number().integer().min(1000).max(new Date().getFullYear()).required()
});
return schema.validate(book);
};
Create Request Handlers
Step 13: Add POST Request Handler
app.post('/api/books', (req, res) => {
const { error } = validateBook(req.body);
if (error) return res.status(400).send(error.details[0].message);
const book = {
id: books.length + 1,
title: req.body.title,
author: req.body.author,
year: req.body.year
};
books.push(book);
res.send(book);
});
Step 14: Add PUT Request Handler
app.put('/api/books/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).send('Book not found');
const { error } = validateBook(req.body);
if (error) return res.status(400).send(error.details[0].message);
book.title = req.body.title;
book.author = req.body.author;
book.year = req.body.year;
res.send(book);
});
Step 15: Add DELETE Request Handler
app.delete('/api/books/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).send('Book not found');
const index = books.indexOf(book);
books.splice(index, 1);
res.send(book);
});
Below is the enhanced example, which demonstrates a complete REST API for managing books, including basic CRUD operations, search functionality, and pagination. You can extend this API with additional features and data as needed for your use case.
// Import required modules
const express = require('express');
const Joi = require('joi');
// Create an instance of an Express application
const app = express();
// Define the port number
const port = 3000;
// Middleware to parse JSON bodies
app.use(express.json());
// Sample data - In-memory data store
const books = [
{ id: 1, title: '1984', author: 'George Orwell', year: 1949 },
{ id: 2, title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960 }
];
// Function to validate book data
const validateBook = (book) => {
const schema = Joi.object({
title: Joi.string().min(3).required(),
author: Joi.string().min(3).required(),
year: Joi.number().integer().min(1000).max(new Date().getFullYear()).required()
});
return schema.validate(book);
};
// Route to get all books
app.get('/api/books', (req, res) => {
res.send(books);
});
// Route to get a specific book by ID
app.get('/api/books/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).send('Book not found');
res.send(book);
});
// Route to create a new book
app.post('/api/books', (req, res) => {
const { error } = validateBook(req.body);
if (error) return res.status(400).send(error.details[0].message);
const book = {
id: books.length + 1,
title: req.body.title,
author: req.body.author,
year: req.body.year
};
books.push(book);
res.send(book);
});
// Route to update an existing book
app.put('/api/books/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).send('Book not found');
const { error } = validateBook(req.body);
if (error) return res.status(400).send(error.details[0].message);
book.title = req.body.title;
book.author = req.body.author;
book.year = req.body.year;
res.send(book);
});
// Route to delete a book
app.delete('/api/books/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).send('Book not found');
const index = books.indexOf(book);
books.splice(index, 1);
res.send(book);
});
// Route to search books by author
app.get('/api/books/search', (req, res) => {
const { author } = req.query;
if (!author) return res.status(400).send('Author query parameter is required');
const filteredBooks = books.filter(b => b.author.toLowerCase().includes(author.toLowerCase()));
res.send(filteredBooks);
});
// Route to paginate books
app.get('/api/books/paginate', (req, res) => {
let { page = 1, size = 10 } = req.query;
page = parseInt(page);
size = parseInt(size);
const startIndex = (page - 1) * size;
const endIndex = startIndex + size;
const paginatedBooks = books.slice(startIndex, endIndex);
res.send(paginatedBooks);
});
// Start the server
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Step 16: Run Your Application with Nodemon
nodemon app.js
Step 17: Test the API
You can use Postman to test the API endpoints:
Get all books:
GET
http://localhost:3000/api/books
Get a book by ID:
GET
http://localhost:3000/api/books/{id}
Create a new book:
POST
http://localhost:3000/api/books
Update a book:
PUT
http://localhost:3000/api/books/{id}
Delete a book:
DELETE
http://localhost:3000/api/books/{id}
Search books by author:
GET
http://localhost:3000/api/books/search?author={author}
Paginate books:
GET
http://localhost:3000/api/books/paginate?page={page}&size={size}
Conclusion
In this tutorial, we've covered the basics of Node.js and Express, set up a development environment, and created a simple REST API with CRUD operations. By following these steps, you should now have a solid foundation for building more complex applications with Node.js and Express.
Happy Coding !!!
Subscribe to my newsletter
Read articles from Prashant Bale directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Prashant Bale
Prashant Bale
With 17+ years in software development and 14+ years specializing in Android app architecture and development, I am a seasoned Lead Android Developer. My comprehensive knowledge spans all phases of mobile application development, particularly within the banking domain. I excel at transforming business needs into secure, user-friendly solutions known for their scalability and durability. As a proven leader and Mobile Architect.