Building a REST API

🌿 Node.js Lesson 11 Intermediate

REST (Representational State Transfer) is the most widely-used API design style. A RESTful API maps resources to URL paths and uses HTTP methods to represent CRUD operations.

1 REST Design Principles
  • Resources & URLs: Resources are nouns (not verbs): /users, /products/:id, /orders/:id/items.
  • HTTP Methods: GET (read), POST (create), PUT/PATCH (update), DELETE (remove).
  • Status Codes: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 500 Server Error.
  • Stateless: Each request must carry all information needed to process it (auth tokens, params).
2 Complete REST API Structure
JavaScript — Complete CRUD API
const express = require('express');
const router = express.Router();

let books = [
  { id: 1, title: 'Node.js in Action', author: 'Manning', year: 2017 }
];
let nextId = 2;

// GET /books — list all
router.get('/', (req, res) => {
  const { author } = req.query;
  const result = author
    ? books.filter(b => b.author.toLowerCase().includes(author.toLowerCase()))
    : books;
  res.json({ data: result, count: result.length });
});

// GET /books/:id — get one
router.get('/:id', (req, res) => {
  const book = books.find(b => b.id === Number(req.params.id));
  if (!book) return res.status(404).json({ error: 'Book not found' });
  res.json(book);
});

// POST /books — create
router.post('/', (req, res) => {
  const { title, author, year } = req.body;
  if (!title || !author) return res.status(400).json({ error: 'title and author required' });
  const book = { id: nextId++, title, author, year: year || new Date().getFullYear() };
  books.push(book);
  res.status(201).json(book);
});

// PATCH /books/:id — partial update
router.patch('/:id', (req, res) => {
  const book = books.find(b => b.id === Number(req.params.id));
  if (!book) return res.status(404).json({ error: 'Book not found' });
  Object.assign(book, req.body);
  res.json(book);
});

// DELETE /books/:id
router.delete('/:id', (req, res) => {
  const idx = books.findIndex(b => b.id === Number(req.params.id));
  if (idx === -1) return res.status(404).json({ error: 'Not found' });
  books.splice(idx, 1);
  res.status(204).send();
});

module.exports = router;
3 Code Challenge
Challenge: Add input validation middleware using a package like express-validator to ensure the POST /books route validates that year is a number between 1900 and the current year.