Developer Guides

How to Build a Node Express REST API with CRUD Operations

Learn to create a Node Express REST API with CRUD operations, including setup, routing, and validation techniques.

6 min read

Learn how to build a Node Express REST API with CRUD operations using this step-by-step guide for developers. We'll cover everything from initialization to deployment, creating an API that includes validation and routing using modern coding practices.

Prerequisites

Before beginning, ensure you have the following:

prerequisites

  • Node.js installed on your system (v16 or later recommended).
  • Basic understanding of JavaScript and Node.js.
  • A code editor, such as Visual Studio Code.
  • Knowledge of HTTP methods (GET, POST, PUT, DELETE) and REST API conventions.

Project Initialization

Follow these steps to set up the project and install necessary dependencies.

steps

  1. Create a new folder (e.g., express-demo).
  2. Open a terminal and navigate into the folder:
    bash
    cd express-demo
  3. Initialize the project with npm:
    bash
    npm init -y
    This will generate a package.json file.
  4. Install Express:
    bash
    npm install express
  5. (Optional) Install nodemon for automatic server restarts:
    bash
    npm install -g nodemon

Setting Up Your First Express Server

In this section, we'll create a basic Express server.

steps

  1. Create a new file called index.js:
    bash
    touch index.js
  2. Add the following code to index.js:
    javascript
    const express = require('express');
    const app = express();
    
    app.use(express.json()); // Middleware for parsing JSON requests
    
    app.get('/', (req, res) => {
        res.send('Welcome to the Express API!');
    });
    
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
  3. Start the server:
    bash
    node index.js
    Or, with nodemon:
    bash
    nodemon index.js
  4. Open a browser and visit http://localhost:3000/ to see the "Welcome to the Express API!" message.

Implementing CRUD Operations

Here, we'll define routes for Create, Read, Update, and Delete actions.

steps

  1. Add the following code to index.js (after the initial setup and before app.listen):
    javascript
    let items = []; // In-memory storage
    
    // Get all items
    app.get('/api/items', (req, res) => {
        res.send(items);
    });
    
    // Get a single item by ID
    app.get('/api/items/:id', (req, res) => {
        const item = items.find(i => i.id === Number(req.params.id));
        if (!item) return res.status(404).send('Item not found');
        res.send(item);
    });
    
    // Create a new item
    app.post('/api/items', (req, res) => {
        if (!req.body.name || req.body.name.length < 3) {
            return res.status(400).send('Name is required and should be at least 3 characters.');
        }
        const newItem = {
            id: items.length + 1,
            name: req.body.name
        };
        items.push(newItem);
        res.send(newItem);
    });
    
    // Update an existing item
    app.put('/api/items/:id', (req, res) => {
        const item = items.find(i => i.id === Number(req.params.id));
        if (!item) return res.status(404).send('Item not found');
    
        if (!req.body.name || req.body.name.length < 3) {
            return res.status(400).send('Name is required and should be at least 3 characters.');
        }
    
        item.name = req.body.name;
        res.send(item);
    });
    
    // Delete an item
    app.delete('/api/items/:id', (req, res) => {
        const item = items.find(i => i.id === Number(req.params.id));
        if (!item) return res.status(404).send('Item not found');
    
        items = items.filter(i => i.id !== Number(req.params.id));
        res.send(item);
    });
  2. Use a REST client like Postman, curl, or a browser extension tool to test the following routes:
    • GET /api/items
    • POST /api/items with a JSON body: { "name": "Sample Item" }
    • PUT /api/items/:id with a JSON body: { "name": "Updated Item" }
    • DELETE /api/items/:id

Organizing Code and Enhancing User Experience

Refactor your project structure to keep the codebase maintainable and reusable.

steps

  1. Create a new folder named routes:
    bash
    mkdir routes
  2. Create a new file in the routes folder for managing items:
    bash
    touch routes/items.js
  3. Move the .get(), .post(), .put(), and .delete() routes to routes/items.js:
    javascript
    const express = require('express');
    const router = express.Router();
    
    let items = []; // In-memory storage
    
    router.get('/', (req, res) => {
        res.send(items);
    });
    
    router.get('/:id', (req, res) => {
        const item = items.find(i => i.id === Number(req.params.id));
        if (!item) return res.status(404).send('Item not found');
        res.send(item);
    });
    
    router.post('/', (req, res) => {
        if (!req.body.name || req.body.name.length < 3) {
            return res.status(400).send('Name is required and should be at least 3 characters.');
        }
        const newItem = {
            id: items.length + 1,
            name: req.body.name
        };
        items.push(newItem);
        res.send(newItem);
    });
    
    router.put('/:id', (req, res) => {
        const item = items.find(i => i.id === Number(req.params.id));
        if (!item) return res.status(404).send('Item not found');
    
        if (!req.body.name || req.body.name.length < 3) {
            return res.status(400).send('Name is required and should be at least 3 characters.');
        }
    
        item.name = req.body.name;
        res.send(item);
    });
    
    router.delete('/:id', (req, res) => {
        const item = items.find(i => i.id === Number(req.params.id));
        if (!item) return res.status(404).send('Item not found');
    
        items = items.filter(i => i.id !== Number(req.params.id));
        res.send(item);
    });
    
    module.exports = router;
  4. Update index.js to use this router:
    javascript
    const express = require('express');
    const itemsRouter = require('./routes/items');
    
    const app = express();
    app.use(express.json());
    
    app.use('/api/items', itemsRouter);
    
    app.get('/', (req, res) => {
        res.send('Welcome to the Express API!');
    });
    
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
  5. Restart your server with nodemon to test the refactored code.

Deploying the Application

Deploying prepares your API for production.

steps

  1. Ensure dynamic port allocation is in place:
    javascript
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
  2. Test thoroughly to ensure all endpoints work as expected.
  3. Choose a hosting provider (e.g., AWS, Heroku, Digital Ocean).
  4. Follow your provider's guides for uploading your application.

FAQ

How do I test a Node Express REST API locally?

You can use tools like Postman, curl, or browser extensions to send HTTP requests to the API endpoints running on your local server (e.g., http://localhost:3000/api).

What is Express used for in a Node.js REST API?

Express is a web framework for Node.js that simplifies building REST APIs by providing a structured way to define routes, handle middleware, and process HTTP requests.

Do I need a database for CRUD operations in Express?

Not necessarily. For simplicity, you can use in-memory storage (like an array) during development, but in production, a database like MongoDB or PostgreSQL is typically used for persistence.


Official reference: Express API reference.