Learn / Frameworks / Express / Routing and Middleware

Beginner 15 min

Routing and Middleware

Route parameters, JSON bodies, and the middleware pipeline.

What you will learn

  • Read params, query and body
  • Write middleware
  • Use routers

Two ideas sit at the heart of Express: routing (which code handles which request) and middleware (a pipeline every request passes through).

app.use(express.json());                 // parse JSON bodies

app.get("/users/:id", (req, res) => {
  res.json({ id: req.params.id, verbose: req.query.verbose });   // /users/7?verbose=1
});

app.post("/users", (req, res) => {
  const { name, email } = req.body;
  res.status(201).json({ name, email });
});
  • req.params: values from the path (:id).
  • req.query: the query string (?page=2).
  • req.body: parsed body; requires the express.json() middleware, otherwise it is undefined.
  • req.headers: request headers.

Middleware

A middleware function receives (req, res, next). It can inspect or change the request, end the response, or call next() to pass control on. They run in the order you register them.

function logger(req, res, next) {
  const start = Date.now();
  res.on("finish", () => {
    console.log(`${req.method} ${req.url} ${res.statusCode} ${Date.now() - start}ms`);
  });
  next();
}

function requireKey(req, res, next) {
  if (req.get("x-api-key") !== "secret") {
    return res.status(401).json({ error: "Unauthorized" });
  }
  next();
}

app.use(logger);                          // for every route
app.get("/private", requireKey, (req, res) => res.json({ ok: true }));   // for one route
Order matters

Register express.json() and your logger before the routes that need them. Forgetting next() leaves the request hanging.

Routers

Split a large app into modules with express.Router().

// routes/users.js
import { Router } from "express";
const router = Router();

router.get("/", (req, res) => res.json([]));
router.get("/:id", (req, res) => res.json({ id: req.params.id }));

export default router;

// index.js
import users from "./routes/users.js";
app.use("/api/users", users);

Useful built-in and third-party middleware

  • express.static("public"): serve files from a folder.
  • cors: allow browsers on other origins to call your API.
  • helmet: set secure HTTP headers.
  • morgan: ready-made request logging.

Try it yourself

Write middleware that adds a req.requestId (a random id) and an X-Request-Id response header, and apply it to all routes.

Show solution
import { randomUUID } from "node:crypto";

app.use((req, res, next) => {
  req.requestId = randomUUID();
  res.setHeader("X-Request-Id", req.requestId);
  next();
});