Mapping URL Patterns to Handlers — Without a Framework
Routing Manually
Match method + path to a handler. Build it once to see what frameworks do for you.
What you'll learn
- Match method + path patterns
- Extract path params and query strings
- Wire a tiny router
node:http gives you raw req.url and req.method. To handle
multiple routes, you build (or use) a router. Here’s the
hand-rolled version — useful to see what frameworks abstract.
A Tiny Router
import { createServer } from "node:http";
const routes = [
{ method: "GET", pattern: /^\/$/, handler: home },
{ method: "GET", pattern: /^\/users$/, handler: listUsers },
{ method: "GET", pattern: /^\/users\/(\d+)$/, handler: getUser },
{ method: "POST", pattern: /^\/users$/, handler: createUser },
];
createServer(async (req, res) => {
const url = new URL(req.url, `http://${req.headers.host}`);
for (const route of routes) {
if (route.method !== req.method) continue;
const match = url.pathname.match(route.pattern);
if (match) {
return route.handler(req, res, match.slice(1));
}
}
res.statusCode = 404;
res.end("not found");
}).listen(3000);
function home(req, res) {
res.end("hello");
}
function listUsers(req, res) {
res.setHeader("content-type", "application/json");
res.end(JSON.stringify([{ id: 1 }, { id: 2 }]));
}
function getUser(req, res, [id]) {
res.setHeader("content-type", "application/json");
res.end(JSON.stringify({ id: Number(id) }));
}
async function createUser(req, res) {
res.statusCode = 201;
res.end("created");
} Pattern-match the URL, dispatch to a handler, pass path params.
Query Strings
const url = new URL(req.url, `http://${req.headers.host}`);
const limit = url.searchParams.get("limit") ?? "10";
const tags = url.searchParams.getAll("tag"); URLSearchParams is the standard API — same in browsers.
Why This Gets Old
Real routers handle:
- Globs (
/posts/*) - Optional params (
/users/:id?) - Wildcards (
/api/*splat) - Method-specific 405 vs 404
- Middleware chains
Reinventing these correctly is a weekend project. Use Express,
Fastify, or any router lib (like find-my-way if you want a tiny
one).
Up Next
The fetch API — same in Node and the browser, for making outbound HTTP calls.