Middleware functions sit between the request and response — they can read/modify the request, execute code, and call the next middleware.

Middleware Signature

  function middleware(req, res, next) {
    // Do something
    next(); // Pass to next middleware
    // If you don't call next(), the request hangs
}
  

Application-Level Middleware

  import express from 'express';
const app = express();

// Runs on every request
app.use((req, res, next) => {
    console.log(`${req.method} ${req.url}`);
    next();
});

app.use(express.json());
  

Route-Level Middleware

  function requireAuth(req, res, next) {
    const token = req.headers.authorization;
    if (!token) {
        return res.status(401).json({ error: 'Unauthorized' });
    }
    // Verify token...
    req.user = { id: 1, name: 'Alice' };
    next();
}

app.get('/profile', requireAuth, (req, res) => {
    res.json(req.user);
});
  

Multiple Middleware

  const validate = (req, res, next) => {
    if (!req.body.email) return res.status(400).json({ error: 'Email required' });
    next();
};

app.post('/users', requireAuth, validate, (req, res) => {
    res.status(201).json(req.body);
});
  

Error-Handling Middleware

Four arguments — Express recognizes error handlers by arity:

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

Common Third-Party Middleware

  npm install cors helmet morgan compression
  
  import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';

app.use(helmet());           // Security headers
app.use(cors());             // Cross-origin requests
app.use(morgan('dev'));      // Request logging
app.use(compression());      // Gzip responses
  

Custom Logger Middleware

  function requestLogger(req, res, next) {
    const start = Date.now();
    res.on('finish', () => {
        const duration = Date.now() - start;
        console.log(`${req.method} ${req.url} ${res.statusCode} ${duration}ms`);
    });
    next();
}

app.use(requestLogger);
  

Async Middleware

Wrap async handlers to catch errors:

  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.findAll();
    res.json(users);
}));
  

Middleware is the core pattern for cross-cutting concerns in Express applications.