Node.jsintermediate 10 min
Create, read, update and delete resources over HTTP with correct methods and status codes.
What REST means, how to map create/read/update/delete (CRUD) to HTTP methods, how to read a JSON body, and which status codes to return.
Almost every app talks to a back end through an API. REST is the common set of conventions, so other developers (and your own front end) can guess how your API works.
REST organises an API around resources (nouns such as todos), each with its own URL. The HTTP method says what to do:
| Action | Method | URL | Success status |
|---|---|---|---|
| List all | GET | /todos | 200 |
| Get one | GET | /todos/1 | 200 |
| Create | POST | /todos | 201 |
| Update | PUT or PATCH | /todos/1 | 200 |
| Delete | DELETE | /todos/1 | 204 |
Common error codes: 400 bad request (invalid input), 404 not found, 500 server error.
To read a JSON body you add the middleware app.use(express.json()), after which req.body holds the parsed object. Here we store data in a simple array in memory. A real API would use a database (a later lesson).
express.json() parses JSON request bodies into req.body.GET /todos returns the whole list with status 200.GET /todos/:id looks the item up. If it does not exist, we return 404 with an error message.POST /todos validates the input (400 if title is missing), creates the item with a new id and returns it with 201 Created.DELETE /todos/:id removes the item and answers 204 No Content, which means success with no body.The script below starts the API, acts as a client with fetch, and prints the status and result of each call. Save it as api.mjs, run npm install express and node api.mjs.
express.json(), so req.body is undefined./getTodos. The method is the verb; the URL is the noun.express.json() and validate input.Next: keeping secrets in environment variables.
import express from "express";
const app = express();
app.use(express.json());
let todos = [{ id: 1, title: "Learn Node", done: false }];
let nextId = 2;
app.get("/todos", (req, res) => res.json(todos));
app.get("/todos/:id", (req, res) => {
const todo = todos.find((t) => t.id === Number(req.params.id));
if (!todo) return res.status(404).json({ error: "Not found" });
res.json(todo);
});
app.post("/todos", (req, res) => {
if (!req.body.title) return res.status(400).json({ error: "title is required" });
const todo = { id: nextId++, title: req.body.title, done: false };
todos.push(todo);
res.status(201).json(todo);
});
app.delete("/todos/:id", (req, res) => {
todos = todos.filter((t) => t.id !== Number(req.params.id));
res.status(204).end();
});
app.listen(3000);