A Node Server: Routes and Handlers
At the other end of fetch('/api/plants') sits a Node.js program that has been waiting on a port. Its whole job is to read each request, pick the right piece of code for it, and send exactly one answer back. Sprout uses Express, the most common small web framework for Node, but every server framework follows the same shape.
The rule
A route is a method plus a path; its handler turns a request into a response.
import express from 'express';
const app = express();
app.use(express.json()); // middleware: parse JSON bodies
app.get('/api/plants', async (req, res) => {
const plants = await listPlants(req.user.id);
res.json(plants); // 200 by default
});
app.post('/api/plants', async (req, res) => {
const plant = await createPlant(req.user.id, req.body);
res.status(201).json(plant);
});
app.listen(3000, () => console.log('Sprout API on port 3000'));app.listen(3000)claims port 3000 and waits. Unlike a script, the process keeps running until it is stopped.- Routes.
GET /api/plantsandPOST /api/plantsshare a path but are different routes, because the method differs. reqis the incoming request:req.paramsholds pieces of the path (/api/plants/:id),req.queryholds the part after?,req.bodyholds the parsed JSON, and headers and cookies are there too.resis how you answer: choose a status, send a body. Every request needs exactly one response; a code path that sends none leaves the browser waiting until it gives up.- Middleware runs before handlers, for many routes at once: parsing JSON, logging, checking the login. It is registered with
app.use, and order matters. JSON must be parsed before any handler readsreq.body.
req.user is filled in by the login middleware you will meet in Section 4. For now, read it as "the person asking".
A single Node process can serve many users at once because handlers await slow work such as database queries. While one request waits for PostgreSQL, the process gets on with others.
The shortcut
To find the code behind any request, read its method and path in the Network tab, then search the server for that route. PATCH /api/plants/7 leads straight to app.patch('/api/plants/:id', ...).
It arrives
PATCH /api/plants/7with the body{"name":"Boston fern"}.
Watch the quotes in that third step: path parameters always arrive as strings. '7' is not 7, so convert with Number(req.params.id) before any arithmetic or strict comparison.
Drills
Answer fast — trust the rule.
Which two things identify a route?
A handler reads req.body.name, but it is always undefined even though the browser sends JSON. What is most likely missing?
One branch of a handler returns without calling any res method. What does the browser experience on that branch?
For the route /api/plants/:id, what is req.params.id for a request to /api/plants/42?
Remember
- A route is a method plus a path; its handler turns a request into a response.
- Shortcut: read method and path in the Network tab, then search the server for that route.
- Trap: path parameters are strings, and a branch that never responds leaves the browser hanging.
