Node.js Express Routing — Complete Guide to Route Handlers and URL Parameters
In this tutorial, you will learn about Node.js Express Routing. We cover key concepts, practical examples, and best practices to help you master this topic.
Express.js routing maps HTTP methods and URL patterns to handler functions, forming the core of request handling in web applications.
What You'll Learn
By the end of this tutorial, you'll define Express routes with parameters and query strings, use Router for modular organization, handle multiple HTTP methods, and structure routes for scalability.
Why Express Routing Matters
Well-organized routing is the foundation of maintainable web applications. Poor routing leads to spaghetti code, duplicated logic, and bugs from inconsistent URL handling.
Real-World Use
An e-commerce API uses Express Router to organize routes into separate files: product routes, cart routes, user routes, and order routes. Each router handles CRUD for its resource.
Express Routing Learning Path
flowchart LR
A[Testing] --> B[Express Routing]
B --> C[Express Middleware]
C --> D[Express Error Handling]
D --> E[REST API]
A --> F{You Are Here}
style F fill:#f90,color:#fff
Basic Route Methods
import express from "express";
const app = express();
app.get("/", (req, res) => res.send("GET request"));
app.post("/", (req, res) => res.send("POST request"));
app.put("/", (req, res) => res.send("PUT request"));
app.delete("/", (req, res) => res.send("DELETE request"));
app.patch("/", (req, res) => res.send("PATCH request"));
app.all("/api/*", (req, res) => res.send("Matches any method on /api/..."));
app.listen(3000);
Route Parameters
app.get("/users/:id", (req, res) => {
res.json({ userId: req.params.id });
});
app.get("/users/:userId/posts/:postId", (req, res) => {
res.json({ userId: req.params.userId, postId: req.params.postId });
});
Query Parameters
app.get("/search", (req, res) => {
const { q, page = 1, limit = 10 } = req.query;
res.json({ query: q, page: Number(page), limit: Number(limit) });
});
// GET /search?q=express&page=2&limit=20
Express Router
import { Router } from "express";
const router = Router();
router.get("/", (req, res) => res.json({ users: [] }));
router.post("/", (req, res) => res.status(201).json({ id: 3 }));
router.get("/:id", (req, res) => {
res.json({ id: req.params.id, name: "Alice" });
});
export default router;
// app.js
import userRoutes from "./routes/users.js";
app.use("/api/users", userRoutes);
Route Pattern Matching
// String pattern
app.get("/ab?cd", (req, res) => res.send("acd or abcd"));
// Regular expression
app.get(/\/api\/v[1-2]\/users/, (req, res) => res.send("v1 or v2 users"));
// Array of handlers
const middle1 = (req, res, next) => { console.log("First"); next(); };
const middle2 = (req, res, next) => { console.log("Second"); next(); };
app.get("/chain", [middle1, middle2], (req, res) => res.send("Done"));
Route Level Middleware
const router = Router();
const requireAuth = (req, res, next) => {
if (!req.headers.authorization) return res.status(401).send("Unauthorized");
next();
};
router.use(requireAuth); // Applied to all routes in this router
router.get("/profile", (req, res) => res.send("Profile data"));
Common Mistakes
1. Defining Routes After app.use(express.static)
Static file middleware catches requests before routes. Place route-specific middleware after static file serving.
2. Overlapping Route Patterns
/users/:id and /users/profile conflict because "profile" matches :id. Define static routes before parameterized routes.
3. Not Using Router for Organization
Having all routes in app.js creates a massive file. Split into routers by resource or feature.
4. Forgetting to Export Router
An exported Router that isn't imported and mounted silently does nothing.
5. Mixing Route and App-Level Middleware Order
Route-level middleware applies only to that router. App-level middleware applies to all routes. Understand the scope.
Practice Questions
1. What is the difference between req.params and req.query?
req.params contains route parameters (e.g., /users/:id). req.query contains URL query string parameters (?page=1).
2. How do you create modular route files in Express?
Use express.Router() to create a router, define routes on it, export it, and mount it in app.js with app.use().
3. What happens when two routes match the same URL pattern?
The first defined route handles the request. Define more specific routes before parameterized routes.
4. How do you handle all HTTP methods on a single path?
Use app.all(path, handler). It matches GET, POST, PUT, DELETE, PATCH, and others.
5. Challenge: Create a router for a blog API with CRUD operations for posts.
import { Router } from "express";
const router = Router();
let posts = [{ id: 1, title: "First Post", body: "Hello" }];
router.get("/", (req, res) => res.json(posts));
router.get("/:id", (req, res) => {
const post = posts.find(p => p.id === Number(req.params.id));
post ? res.json(post) : res.status(404).send("Not found");
});
router.post("/", (req, res) => {
const post = { id: posts.length + 1, ...req.body };
posts.push(post);
res.status(201).json(post);
});
router.put("/:id", (req, res) => {
const idx = posts.findIndex(p => p.id === Number(req.params.id));
if (idx === -1) return res.status(404).send("Not found");
posts[idx] = { ...posts[idx], ...req.body };
res.json(posts[idx]);
});
router.delete("/:id", (req, res) => {
posts = posts.filter(p => p.id !== Number(req.params.id));
res.status(204).send();
});
export default router;
FAQ
Mini Project: Blog API Router
Create a complete blog API with Express Router.
const express = require("express");
const app = express();
app.use(express.json());
const postsRouter = require("./routes/posts");
const commentsRouter = require("./routes/comments");
app.use("/api/posts", postsRouter);
app.use("/api/comments", commentsRouter);
app.listen(3000);
What's Next
Express Middleware Express Error Handling REST API Express
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro