Learnwizy Technologies Logo

Learnwizy Technologies

Class 24: Building a RESTful API with Express (CRUD - Read)

Now that we understand the principles of RESTful APIs, it's time to start building one! We'll begin with the "Read" operations of CRUD (Create, Read, Update, Delete), which are typically the simplest to implement.

For now, we'll use an in-memory JavaScript array to simulate a database. This allows us to focus purely on the Express.js API implementation without getting bogged down by database connections just yet.


Introduction to CRUD Operations

CRUD is an acronym that stands for the four basic operations of persistent storage:

Almost every web application interacts with data using these four fundamental operations.


Designing API Endpoints for Resources

Following REST principles, we'll choose a resource to manage. Let's pick "Books" for our example.

Our base URL for the API will be /api/books.

Operation HTTP Method Endpoint Description
Get All Books GET /api/books Retrieve a list of all books.
Get Single Book GET /api/books/:id Retrieve a single book by its ID.
Create Book POST /api/books Add a new book to the collection.
Update Book PUT /api/books/:id Update an existing book by its ID (full replacement).
Delete Book DELETE /api/books/:id Remove a book by its ID.

In-Memory Data Storage (Dummy Data)

To simulate a database, we'll use a simple JavaScript array of objects. In a real application, this data would come from a persistent database like PostgreSQL, MongoDB, etc.

// server.js
const express = require('express');
const app = express();
const port = 3000;

// In-memory array to simulate our database
let books = [
  { id: '1', title: 'The Hitchhiker\'s Guide to the Galaxy', author: 'Douglas Adams', year: 1979 },
  { id: '2', title: '1984', author: 'George Orwell', year: 1949 },
  { id: '3', title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960 }
];

// Middleware to parse JSON bodies (needed for POST/PUT/PATCH later)
app.use(express.json());

// Start the server
app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

Using in-memory data is great for rapid prototyping and learning API concepts because it removes the complexity of database setup and operations.


Implementing GET All Resources

This endpoint will allow clients to retrieve a list of all books in our collection.

// server.js (continued)

// GET /api/books - Get all books
app.get('/api/books', (req, res) => {
  if (books.length === 0) {
    return res.status(200).json({ message: 'No books found.', data: [] });
  }
  res.status(200).json(books); // Send the array of books as JSON with 200 OK status
});

// ... app.listen() remains the same

Test it: Open your browser or API client (Postman/Insomnia) and go to http://localhost:3000/api/books. You should see the JSON array of books.


Implementing GET Single Resource by ID

This endpoint will allow clients to retrieve a specific book by its unique ID.

// server.js (continued)

// GET /api/books/:id - Get a single book by ID
app.get('/api/books/:id', (req, res) => {
  const bookId = req.params.id; // Get the ID from the URL parameters
  const book = books.find(b => b.id === bookId); // Find the book in our array

  if (book) {
    res.status(200).json(book); // Book found, send it
  } else {
    res.status(404).json({ message: `Book with ID ${bookId} not found.` }); // Book not found
  }
});

// ... app.listen() remains the same

Test it:


Postman/Insomnia for API Testing (Basic)

While you can test GET requests directly in your browser, for POST, PUT, PATCH, and DELETE requests, you'll need an API client tool.

Two popular choices are:

You can download and install either of these for free. They allow you to:

For the GET requests we just built, you can use Postman/Insomnia to send requests to http://localhost:3000/api/books and http://localhost:3000/api/books/1 and observe the responses, including the status codes. This will be essential for testing the Create, Update, and Delete operations in the next classes.