# Middleware in Express

Every HTTP request that hits your Express server has a journey to make from the moment it arrives to the moment a response goes back. Middleware is what lives in between.

## The Simplest Definition

Middleware is a function that runs *between* the incoming request and the final route handler.

That's it. Any function in Express that receives `req`, `res`, and `next` is middleware.

```javascript
function myMiddleware(req, res, next) {
  // do something with the request or response
  next(); // pass control to the next function
}
```

Three parameters. That's the signature. The `next` function is what makes it middleware rather than a route handler calling `next()` says "I'm done, pass this request to whoever is registered next."

## Middleware in the Request Lifecycle

Think of every Express request as going through a pipeline — a series of checkpoints before it reaches the final destination. Each checkpoint can inspect the request, modify it, add data to it, block it entirely, or pass it through.

```plaintext
Incoming request
      ↓
  [Middleware 1]   ← logging: log method + URL, call next()
      ↓
  [Middleware 2]   ← auth: check token, call next() or return 401
      ↓
  [Middleware 3]   ← body parser: parse JSON into req.body, call next()
      ↓
  [Route handler]  ← do the actual work, send the response
      ↓
Outgoing response
```

Every function in that chain gets the same `req` and `res` objects. If middleware attaches something to `req` say, `req.user = decodedToken` every function after it in the chain can access `req.user`. This is how authentication middleware passes the authenticated user to a route handler.

## The `next()` Function

`next()` is what keeps the chain alive. When middleware calls `next()`, Express moves to the next registered function. When middleware doesn't call `next()` (and doesn't send a response either), the request just hangs. The client waits forever. This is one of the most common Express bugs a middleware that silently swallows requests.

```javascript
// Correct — always either call next() or send a response
function checkHeader(req, res, next) {
  if (!req.headers['x-api-key']) {
    return res.status(401).json({ error: 'API key required' });
    // we're done — no next() needed, response is sent
  }
  next(); // key exists — move on
}
```

Two exits: send a response (and stop), or call `next()` (and continue). Every middleware must do one of the two.

**What most tutorials don't explain about** `next()`**:** you can pass an argument to `next()`. Passing anything (by convention, an error object) skips all remaining regular middleware and jumps directly to an *error-handling* middleware:

```javascript
function riskyOperation(req, res, next) {
  try {
    const result = doSomethingDangerous();
    next();
  } catch (err) {
    next(err); // skip to error handler
  }
}

// Error-handling middleware: 4 parameters, always (err, req, res, next)
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Something went wrong' });
});
```

The four-parameter signature is Express's convention for error handlers. Express identifies them specifically by the number of parameters not by name, not by position, just by arity. If you write `(err, req, res, next)`, Express treats it as an error handler and only calls it when `next(err)` is called somewhere upstream.

## Types of Middleware

### Application-level middleware

Registered on the `app` object with `app.use()`. Runs for every matching request.

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

// Runs only for requests to /api/*
app.use('/api', (req, res, next) => {
  console.log('API request received');
  next();
});
```

### Router-level middleware

The same concept, but attached to an `express.Router()` instance instead of the app. This is how you apply middleware only to a subset of routes:

```javascript
const router = express.Router();

// Applies to all routes in this router
router.use((req, res, next) => {
  console.log('Router-level middleware');
  next();
});

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

app.use('/users', router);
```

If you mount this router at `/users`, the middleware only runs for requests to `/users/*`.

### Built-in middleware

Express ships with a few middleware functions out of the box — no extra packages needed:

`express.json()` — parses request bodies with `Content-Type: application/json`. Makes them available as `req.body`.

```javascript
app.use(express.json());
```

`express.urlencoded({ extended: true })` — parses URL-encoded form data (the kind HTML forms submit). Makes it available as `req.body`.

```javascript
app.use(express.urlencoded({ extended: true }));
```

`express.static(directory)` — serves static files (HTML, CSS, images, JS) from a folder.

```javascript
app.use(express.static('public')); // serves files from ./public
```

These are the ones you'll register on almost every Express app. There's also `express.raw()` and `express.text()` for other content types, but they're less commonly needed.

## Execution Order:

Middleware runs in the exact order it's registered. There are no priorities, no weights just top to bottom.

```js
app.use(loggerMiddleware);      // 1 — runs first
app.use(express.json());        // 2 — then body parsing
app.use(authMiddleware);        // 3 — then authentication

app.get('/dashboard', (req, res) => {
  // 4 — route handler (only if all middleware called next())
  res.json({ page: 'dashboard', user: req.user });
});
```

A request to `GET /dashboard` runs through all four in sequence. If `authMiddleware` returns a `401`, the route handler never runs.

**What happens with multiple route handlers matching the same path?** They run in order too. This is less obvious but occasionally useful:

```js
app.get('/users/:id', loadUser);     // attaches user to req
app.get('/users/:id', checkAccess);  // verifies req.user can see this user
app.get('/users/:id', sendResponse); // sends the response
```

Three separate handler registrations for the same route. Each calls `next()` to pass to the next. This is called "route chaining" and it's a valid (if uncommon) pattern for decomposing complex route logic.

## Real-World Examples

### Logging middleware

```javascript
function logger(req, res, next) {
  const start = Date.now();

  // Intercept res.end to know when the response was sent
  const originalEnd = res.end.bind(res);
  res.end = function (...args) {
    const duration = Date.now() - start;
    console.log(`${req.method} ${req.url} ${res.statusCode} — ${duration}ms`);
    return originalEnd(...args);
  };

  next();
}

app.use(logger);
```

Middleware is a conveyor belt. Each station on the belt can inspect the item, stamp it, reject it, or pass it along. The `req` and `res` objects are the item they get passed from station to station. `next()` is the button that moves the belt forward.

Some stations are always running (global middleware). Some only activate for certain routes. Some are fail-safes at the end (error handlers). Together, they turn a raw HTTP request into a handled, validated, authenticated, logged transaction.

Once you see Express this way, the whole framework clicks.
