Advanced Middleware Patterns

1. Creating Factory Functions

Example: Configurable middleware factory

export function requirePlan(...plans) {
  return (req, res, next) => {
    if (!plans.includes(req.user?.plan)) return next(new HttpError(402));
    next();
  };
}

app.get("/pro", requireAuth, requirePlan("pro","enterprise"), proHandler);

2. Implementing Conditional Middleware

Example: ifEnv helper

const onlyIn = (env, mw) => (req, res, next) => process.env.NODE_ENV === env ? mw(req, res, next) : next();
app.use(onlyIn("development", morgan("dev")));

3. Using Middleware Composition

Example: compose

function compose(...mws) {
  return (req, res, next) => {
    let i = 0;
    const run = (err) => {
      if (err) return next(err);
      const mw = mws[i++];
      if (!mw) return next();
      mw(req, res, run);
    };
    run();
  };
}

app.use(compose(requireAuth, requireRole("admin"), loadOrg()));

4. Creating Configurable Middleware

Example: Options + defaults

export function timeout(opts = {}) {
  const { ms = 30_000, message = "Request timed out" } = opts;
  return (req, res, next) => {
    const t = setTimeout(() => {
      if (!res.headersSent) res.status(503).json({ error: message });
    }, ms);
    res.on("finish", () => clearTimeout(t));
    res.on("close",  () => clearTimeout(t));
    next();
  };
}

5. Implementing Error Recovery Middleware

Example: Retry on transient error

function retry(fn, { tries = 3 } = {}) {
  return async (req, res, next) => {
    for (let i = 0; i < tries; i++) {
      try { return await fn(req, res, next); }
      catch (err) {
        if (i === tries - 1 || !err.retryable) return next(err);
      }
    }
  };
}

6. Using Middleware for Request Transformation

Example: Trim string fields

function trimStrings(obj) {
  if (!obj || typeof obj !== "object") return obj;
  for (const k of Object.keys(obj)) {
    if (typeof obj[k] === "string") obj[k] = obj[k].trim();
    else if (typeof obj[k] === "object") trimStrings(obj[k]);
  }
}
app.use((req, res, next) => { trimStrings(req.body); next(); });

7. Implementing Response Time Middleware

Example: response-time

import responseTime from "response-time";
app.use(responseTime((req, res, time) => {
  res.set("X-Response-Time", time.toFixed(1) + "ms");
  metrics.histogram("http_request_ms").observe(time);
}));

8. Creating Request ID Middleware

Example: Request ID

import { randomUUID } from "node:crypto";
app.use((req, res, next) => {
  req.id = req.get("X-Request-Id") || randomUUID();
  res.set("X-Request-Id", req.id);
  next();
});

9. Implementing Throttling Middleware

Example: Per-user concurrency limit

const inflight = new Map();
export function maxConcurrent(n) {
  return (req, res, next) => {
    const key = req.user?.sub || req.ip;
    const count = inflight.get(key) || 0;
    if (count >= n) return next(new HttpError(429, "Too many concurrent requests"));
    inflight.set(key, count + 1);
    res.on("finish", () => inflight.set(key, (inflight.get(key) || 1) - 1));
    next();
  };
}

10. Using Middleware for Feature Flags

Example: Flag-gated route

export const requireFlag = (flag) => async (req, res, next) => {
  const enabled = await flags.isEnabled(flag, { userId: req.user?.sub });
  enabled ? next() : next(new HttpError(404));  // hide route entirely
};

app.get("/beta/feature", requireAuth, requireFlag("beta_feature"), betaHandler);