Express Cheatsheet

Middleware

Use this Express reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

What Is Middleware

A middleware function has the signature (req, res, next) (or (err, req, res, next) for errors). It runs in order, must call next() to continue, or end the response itself.

// Minimal middleware
const logger = (req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next(); // pass control to next middleware or route
};

app.use() — Mounting Middleware

// Apply to ALL routes, ALL methods
app.use(logger);

// Apply to all routes under /api
app.use('/api', logger);

// Multiple middleware in one call
app.use(express.json(), express.urlencoded({ extended: true }), logger);

// Array
app.use([cors(), helmet(), logger]);

Middleware Execution Order

Order of app.use() and route registrations defines execution order — registration order is matching order.

app.use(parseBody);      // 1st: runs for every request
app.use(authenticate);   // 2nd
app.get('/public', publicHandler);  // only for GET /public
app.use(authorise);      // 3rd: runs after publicHandler
app.get('/admin', adminHandler);
app.use(notFoundHandler); // last: 404 fallback

Types of Middleware

Application-Level

app.use((req, res, next) => { /* runs on every request */ next(); });
app.use('/path', (req, res, next) => { /* runs only under /path */ next(); });

Router-Level

const router = express.Router();
router.use((req, res, next) => { /* scoped to this router */ next(); });

Error-Handling

Must have exactly four parameters — Express detects the arity.

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(err.status || 500).json({ error: err.message });
});

Trigger with next(err) or next(new Error('something')) from any handler.

Third-Party

const morgan  = require('morgan');
const cors    = require('cors');
const helmet  = require('helmet');

app.use(morgan('combined'));
app.use(cors());
app.use(helmet());

Built-In (Express 4.16+)

MiddlewarePurpose
express.json(options)Parse application/json bodies
express.urlencoded(options)Parse application/x-www-form-urlencoded
express.raw(options)Parse body as Buffer
express.text(options)Parse body as string
express.static(root, options)Serve static files

Conditional Middleware

// Skip in test environment
if (process.env.NODE_ENV !== 'test') {
  app.use(morgan('dev'));
}

// Skip for a specific path
app.use((req, res, next) => {
  if (req.path === '/health') return next();
  return authenticate(req, res, next);
});

// Express-unless pattern (common helper)
const unless = (path, middleware) => (req, res, next) =>
  req.path === path ? next() : middleware(req, res, next);

app.use(unless('/login', authenticate));

Writing Reusable Middleware (Factory Pattern)

Return a middleware function from a factory for configurable behavior.

const rateLimit = (limit, windowMs) => {
  const counts = new Map();
  return (req, res, next) => {
    const key = req.ip;
    const now = Date.now();
    const entry = counts.get(key) || { count: 0, start: now };

    if (now - entry.start > windowMs) {
      entry.count = 0; entry.start = now;
    }
    entry.count++;
    counts.set(key, entry);

    if (entry.count > limit) {
      return res.status(429).json({ error: 'Too many requests' });
    }
    next();
  };
};

app.use('/api', rateLimit(100, 60_000));

Async Middleware

Express 4 does not catch rejected promises automatically — wrap or use a helper.

// Manual try/catch
app.use(async (req, res, next) => {
  try {
    req.user = await findUser(req.headers.authorization);
    next();
  } catch (err) {
    next(err);
  }
});

// Async wrapper utility
const asyncHandler = fn => (req, res, next) =>
  Promise.resolve(fn(req, res, next)).catch(next);

app.get('/users', asyncHandler(async (req, res) => {
  const users = await db.query('SELECT * FROM users');
  res.json(users);
}));

Express 5 automatically forwards rejected promises to next(err) — no wrapper needed.

Modifying req and res in Middleware

// Attach data to req for downstream handlers
app.use(async (req, res, next) => {
  req.requestId = crypto.randomUUID();
  req.startTime = Date.now();
  next();
});

// Wrap res.json to add envelope
app.use((req, res, next) => {
  const originalJson = res.json.bind(res);
  res.json = (data) => originalJson({ data, requestId: req.requestId });
  next();
});

Middleware Short-Circuiting

const authenticate = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'Unauthorized' }); // end here
  try {
    req.user = jwt.verify(token, process.env.JWT_SECRET);
    next(); // continue
  } catch {
    res.status(401).json({ error: 'Invalid token' }); // end here
  }
};

Common Third-Party Middleware

PackagePurposeUsage
morganHTTP request loggerapp.use(morgan('dev'))
corsCORS headersapp.use(cors(options))
helmetSecurity headersapp.use(helmet())
compressionGzip responsesapp.use(compression())
multerFile uploads (multipart)router.post('/', upload.single('file'), handler)
express-rate-limitRate limitingapp.use('/api', rateLimit({ windowMs, max }))
express-validatorInput validation[body('email').isEmail(), validationResult]
cookie-parserParse cookiesapp.use(cookieParser(secret))
express-sessionSession supportapp.use(session({ secret, resave, saveUninitialized }))
passportAuthentication strategiesapp.use(passport.initialize())