Custom Routing and Middlewares
In a production web application, handling all server logic inside a single monolithic callback quickly becomes unmaintainable. To resolve this, we can implement custom routers to isolate paths and middleware pipelines to handle cross-cutting concerns (like logging or authentication).
1. Modular Routing Architecture
Let us design a router container that matches incoming request paths and HTTP methods against registered handler functions:
import http from "http";
class SimpleRouter {
constructor() {
this.routes = {
GET: {},
POST: {}
};
}
get(path, handler) {
this.routes.GET[path] = handler;
}
post(path, handler) {
this.routes.POST[path] = handler;
}
handle(req, res) {
const method = req.method;
const path = req.url;
const handler = this.routes[method] ? this.routes[method][path] : null;
if (handler) {
handler(req, res);
} else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Route not found");
}
}
}
// Setup and register routes
const router = new SimpleRouter();
router.get("/api/health", (req, res) => {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ status: "alive" }));
});
const server = http.createServer((req, res) => router.handle(req, res));
server.listen(3000);2. Understanding Middleware (The Onion Model)
Middlewares are callback functions that sit between the server receiving a request and sending a response. Each middleware has access to the request object, response object, and a next callback to hand over control to the subsequent handler in line.
3. Implementing a Middleware Engine
Let us write a miniature middleware runner that runs registered tasks sequentially before executing the primary route handler:
import http from "http";
class AppServer {
constructor() {
this.middlewares = [];
}
// Register middleware
use(middleware) {
this.middlewares.push(middleware);
}
handle(req, res) {
let index = 0;
// Define next function runner
const next = () => {
if (index < this.middlewares.length) {
const middleware = this.middlewares[index];
index += 1;
middleware(req, res, next);
} else {
// Fallback main route handler
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Final handler reached");
}
};
// Start execution chain
next();
}
}
const app = new AppServer();
// Middleware 1: Logger
app.use((req, res, next) => {
console.log(`[LOG] Request received: ${req.method} ${req.url}`);
next(); // Pass control to the next middleware
});
// Middleware 2: Basic Auth check
app.use((req, res, next) => {
const token = req.headers["authorization"];
if (token === "mysecret") {
next();
} else {
res.writeHead(401, { "Content-Type": "text/plain" });
res.end("Unauthorized request token");
}
});
const server = http.createServer((req, res) => app.handle(req, res));
server.listen(3000);