Routing: methods and paths

Express · Essentials · 10 min

Routes are the public surface of your API; organising them well keeps an app understandable.

A route is method + path + one or more handlers. Express has a method for each HTTP verb: app.get, app.post, app.put, app.patch, app.delete, plus app.all for every method.

Routes are checked in the order you register them, and the first one that matches and sends a response wins. Put specific routes before general ones: /users/me must come before /users/:id, or me is treated as an id.

Path matching details:

  • Matching is case-insensitive and ignores a trailing slash by default (/about matches /about/).
  • The query string is not part of the path: /search?q=x matches /search.
  • HEAD requests are answered by your GET routes automatically, without a body.
  • You can pass an array of paths: app.get(["/", "/home"], handler).

When several methods share a path, app.route(path) chains them and avoids repeating the string:

app.route("/books")
  .get(listBooks)
  .post(createBook);

A route can take several handlers; each calls next() to pass control to the following one. That is how per-route middleware (checking a login, loading a record) is attached: app.delete("/posts/:id", requireLogin, deletePost).

Express 5 dropped app.del() — use app.delete(). If a path exists but not for the requested method, Express returns 404, not 405; add an app.all fallback for that path if you want a proper 405 Method Not Allowed with an Allow header.

Example

import express from "express";
const app = express();

const books = [{ id: 1, title: "Dune" }];

function requireApiKey(req, res, next) {
  if (req.get("x-api-key") === "secret") return next();   // pass to the next handler
  res.status(401).json({ error: "missing or bad API key" });
}

app.get("/books/latest", (req, res) => res.json(books.at(-1)));  // before /books/:id

app.route("/books")
  .get((req, res) => res.json(books))
  .post(requireApiKey, (req, res) => res.status(201).json({ created: true }))
  .all((req, res) => res.set("Allow", "GET, POST").status(405).end());

app.get(["/", "/home"], (req, res) => res.send("Welcome"));

app.listen(3000);
// curl -X POST localhost:3000/books              -> 401
// curl -X DELETE localhost:3000/books            -> 405

Remember

  • Routes match in registration order — specific before general
  • app.route(path) chains several methods on one path
  • A route can have several handlers linked with next()

Watch out for

  • Declaring /users/:id before /users/me, so me is captured as an id.

Check yourself

  1. Routes are registered as GET /items/:id then GET /items/new. What handles GET /items/new?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: expressjs.com/en/guide/routing