Building a RESTful API
In this section, we’ll explore how to build a RESTful API using Express. We’ll cover the principles of REST (Representational State Transfer) and demonstrate how to implement CRUD (Create, Read, Update, Delete) operations in your API.
Understanding REST Principles
REST is an architectural style for designing networked applications. It relies on stateless, client-server communication and uses standard HTTP methods. The key principles of REST include:
- Statelessness: Each request from a client to a server must contain all the information needed to understand and process the request.
- Client-Server Architecture: The client and server are separate entities that communicate over a network.
- Uniform Interface: Resources are identified by URLs, and interactions with these resources are performed using standard HTTP methods (GET, POST, PUT, DELETE).
- Resource Representation: Resources are represented in a format such as JSON or XML.
Setting Up the Project
Create a Project Directory:
bash mkdir rest-api cd rest-api
Initialize a Node.js Project:
bash npm init -y
Install Express:
bash npm install express
Create the Entry Point: Create a file named
app.js
:javascript // Importing the Express module const express = require('express'); const app = express(); const port = 3000; // Middleware to parse JSON request bodies app.use(express.json()); // Starting the server app.listen(port, () => { console.log(`Server running at http://localhost:${port}/`); });
Implementing CRUD Operations
Defining the Data Structure: For this example, we’ll create a simple in-memory array to store data about books.
javascript // Sample data let books = [ { id: 1, title: '1984', author: 'George Orwell' }, { id: 2, title: 'To Kill a Mockingbird', author: 'Harper Lee' } ];
Create (POST):
javascript // Handling POST request to create a new book app.post('/books', (req, res) => { const newBook = { id: books.length + 1, title: req.body.title, author: req.body.author }; books.push(newBook); res.status(201).json(newBook); // Sending the created book as a response });
Read (GET):
javascript // Handling GET request to retrieve all books app.get('/books', (req, res) => { res.json(books); // Sending the list of books as a response }); // Handling GET request to retrieve a book by ID app.get('/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.json(book); // Sending the book as a response });
Update (PUT):
javascript // Handling PUT request to update a book by ID app.put('/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'); book.title = req.body.title; book.author = req.body.author; res.json(book); // Sending the updated book as a response });
Delete (DELETE):
javascript // Handling DELETE request to remove a book by ID app.delete('/books/:id', (req, res) => { const bookIndex = books.findIndex((b) => b.id === parseInt(req.params.id)); if (bookIndex === -1) return res.status(404).send('Book not found'); const deletedBook = books.splice(bookIndex, 1); res.json(deletedBook); // Sending the deleted book as a response });
Complete app.js
file:
// Importing the Express module
const express = require('express');
const app = express();
const port = 3000;
// Middleware to parse JSON request bodies
app.use(express.json());
// Sample data
let books = [
{ id: 1, title: '1984', author: 'George Orwell' },
{ id: 2, title: 'To Kill a Mockingbird', author: 'Harper Lee' }
];
// Handling POST request to create a new book
app.post('/books', (req, res) => {
const newBook = {
id: books.length + 1,
title: req.body.title,
author: req.body.author
};
books.push(newBook);
res.status(201).json(newBook); // Sending the created book as a response
});
// Handling GET request to retrieve all books
app.get('/books', (req, res) => {
res.json(books); // Sending the list of books as a response
});
// Handling GET request to retrieve a book by ID
app.get('/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.json(book); // Sending the book as a response
});
// Handling PUT request to update a book by ID
app.put('/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');
book.title = req.body.title;
book.author = req.body.author;
res.json(book); // Sending the updated book as a response
});
// Handling DELETE request to remove a book by ID
app.delete('/books/:id', (req, res) => {
const bookIndex = books.findIndex((b) => b.id === parseInt(req.params.id));
if (bookIndex === -1) return res.status(404).send('Book not found');
const deletedBook = books.splice(bookIndex, 1);
res.json(deletedBook); // Sending the deleted book as a response
});
// Starting the server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Testing Your API
You can use tools like Postman or curl to test your API endpoints.
Here’s how to test each CRUD operation using curl:
Create (POST):
bash curl -X POST -H "Content-Type: application/json" -d '{"title":"The Great Gatsby", "author":"F. Scott Fitzgerald"}' http://localhost:3000/books
Read (GET):
bash curl http://localhost:3000/books curl http://localhost:3000/books/1
Update (PUT):
bash curl -X PUT -H "Content-Type: application/json" -d '{"title":"1984", "author":"George Orwell"}' http://localhost:3000/books/1
Delete (DELETE):
bash curl -X DELETE http://localhost:3000/books/1
Lesson task
Create a RESTful API with CRUD operations for a simple resource (e.g., books, users, products). Test your API using Postman or curl.
Goal
Demonstrate you can build a basic server and implement CRUD operations for a RESTful API.
Brief
Create a new project directory and set up an Express server.
Define a data structure to store information about a resource (e.g., books, users, products).
Add the necessary routes to handle CRUD operations for the resource.
Add the end-points to Postman and test each operation (Create, Read, Update, Delete).
NOTE: Lesson tasks do not get submitted on Moodle and are not assessed by tutors. They are mainly there for you to practise what you have learned in the lesson.