Skip to content

Middleware

BrewedSys edited this page Mar 30, 2026 · 1 revision

Middleware

Http-native supports Express-style middleware with a (req, res, next) signature.

How Middleware Works

Middleware functions run in the order they are registered, before the route handler. Call next() to pass control to the next middleware or handler.

app.use(async (req, res, next) => {
  console.log(`${req.method} ${req.path}`);
  next();
});

If you don't call next(), the request stops at that middleware. This is useful for auth checks:

app.use(async (req, res, next) => {
  const token = req.header("Authorization");
  if (!token) {
    return res.status(401).json({ error: "Unauthorized" });
  }
  next();
});

Global Middleware

Register with app.use() to run on every request:

// Logging
app.use(async (req, res, next) => {
  const start = Date.now();
  next();
  console.log(`${req.method} ${req.path}${Date.now() - start}ms`);
});

// Request ID
app.use(async (req, res, next) => {
  res.locals.requestId = crypto.randomUUID();
  res.set("X-Request-Id", res.locals.requestId);
  next();
});

Path-Scoped Middleware

Pass a path prefix as the first argument to app.use(). The middleware only runs when the request path starts with that prefix.

// Only runs for /api/* routes
app.use("/api", async (req, res, next) => {
  const token = req.header("Authorization");
  if (!token) {
    return res.status(401).json({ error: "API key required" });
  }
  next();
});

// Only runs for /admin/* routes
app.use("/admin", async (req, res, next) => {
  if (!res.locals.user?.isAdmin) {
    return res.status(403).json({ error: "Forbidden" });
  }
  next();
});

Sharing Data Between Middleware

Use res.locals to pass data from middleware to route handlers:

app.use(async (req, res, next) => {
  const token = req.header("Authorization");
  res.locals.user = await verifyToken(token);
  next();
});

app.get("/profile", async (req, res) => {
  res.json(res.locals.user);
});

Middleware Order

Middleware runs in registration order. Register them before the routes that should use them:

// 1. Logging (runs first)
app.use(logger);

// 2. Auth check (runs second)
app.use("/api", authMiddleware);

// 3. Route handler (runs last)
app.get("/api/users", listUsers);

Built-in Middleware

Http-native ships with several middleware modules:

Module Import Description
CORS @http-native/core/cors Cross-Origin Resource Sharing
Sessions @http-native/core/session Rust-backed session management
Validation @http-native/core/validate Schema-agnostic request validation
Hot Reload @http-native/core/hot Development-time file watching

Clone this wiki locally