# What is Middleware in Express and How It Works

Middleware sits between incoming requests and your route handlers. It intercepts requests, does something with them, and either passes them along or stops them. Understanding middleware is key to building Express applications.

## What Is Middleware?

Middleware is a function that has access to the request and response objects. It can modify them, perform checks, or stop the request.

Think of middleware as checkpoints in an airport:

*   Security check (middleware validates the request)
    
*   Baggage scan (middleware processes data)
    
*   Gate (final destination/route handler)
    

Each checkpoint can allow you through to the next, or stop you.

In Express, middleware functions have this signature:

```javascript
function middleware(req, res, next) {
  // Do something
  next(); // Pass to next middleware
}
```

The `next()` function passes control to the next middleware or route handler.

## How Middleware Works

When a request arrives, Express processes it through middleware in order:

```plaintext
Request comes in
     |
     v
Middleware 1 (if next() called, continue)
     |
     v
Middleware 2 (if next() called, continue)
     |
     v
Route Handler (your actual route)
     |
     v
Response sent
```

Each middleware either calls `next()` to continue or sends a response to stop.

## Using Express-Provided Middleware

Express provides built-in middleware for common tasks:

```javascript
import express from 'express';

const app = express();

// Parse JSON requests
app.use(express.json());

// Parse URL-encoded form data
app.use(express.urlencoded({ extended: true }));

// Serve static files
app.use(express.static('public'));

app.post('/data', (req, res) => {
  // Thanks to express.json() middleware, req.body is parsed
  console.log(req.body);
  res.send('Data received');
});

app.listen(3000);
```

`express.json()` middleware automatically parses incoming JSON and populates `req.body`.

## Creating Custom Middleware

Write your own middleware for custom logic:

```javascript
import express from 'express';

const app = express();

// Custom logging middleware
function logger(req, res, next) {
  console.log(`${req.method} ${req.url}`);
  next(); // Pass to next middleware
}

app.use(logger);

app.get('/', (req, res) => {
  res.send('Home page');
});

app.listen(3000);
```

Every request is logged, then passed to the route handler.

Output for `GET /`:

```plaintext
GET /
```

## Middleware Execution Order

Middleware runs in the order you define it:

```javascript
import express from 'express';

const app = express();

app.use((req, res, next) => {
  console.log('1: First middleware');
  next();
});

app.use((req, res, next) => {
  console.log('2: Second middleware');
  next();
});

app.get('/', (req, res) => {
  console.log('3: Route handler');
  res.send('Done');
});

app.listen(3000);
```

For a `GET /` request, output is:

```plaintext
1: First middleware
2: Second middleware
3: Route handler
```

Order matters. Middleware defined first runs first.

## The `next()` Function

Calling `next()` passes control to the next function in the chain. Not calling it stops execution:

```javascript
app.use((req, res, next) => {
  console.log('Middleware 1');
  next(); // Continue
});

app.use((req, res, next) => {
  console.log('Middleware 2');
  // Not calling next() - stops here
});

app.get('/', (req, res) => {
  console.log('Route'); // Never reached
  res.send('Hi');
});
```

This stops at "Middleware 2". The route handler is never called.

## Types of Middleware

### Application-Level Middleware

Runs for all routes or specific routes:

```javascript
import express from 'express';

const app = express();

// Runs for ALL routes
app.use((req, res, next) => {
  console.log('Global middleware');
  next();
});

// Runs only for /admin routes
app.use('/admin', (req, res, next) => {
  console.log('Admin middleware');
  next();
});

app.get('/', (req, res) => res.send('Home'));
app.get('/admin/users', (req, res) => res.send('Admin page'));

app.listen(3000);
```

### Router-Level Middleware

Middleware on a specific router:

```javascript
import express from 'express';

const app = express();
const router = express.Router();

router.use((req, res, next) => {
  console.log('Router middleware');
  next();
});

router.get('/users', (req, res) => res.send('Users'));

app.use('/api', router);
app.listen(3000);
```

### Built-In Middleware

Express provides standard middleware:

```javascript
app.use(express.json());
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true }));
```

### Third-Party Middleware

Use packages from npm:

```bash
npm install cors
```

```javascript
import cors from 'cors';

app.use(cors()); // Enable CORS
```

## Real-World Middleware Examples

### Authentication Middleware

```javascript
function authenticateToken(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];

  if (!token) {
    return res.status(401).send('No token');
  }

  // Verify token (simplified)
  if (token === 'valid-token') {
    req.user = { id: 1 };
    next();
  } else {
    res.status(403).send('Invalid token');
  }
}

app.get('/protected', authenticateToken, (req, res) => {
  res.send(`Hello user ${req.user.id}`);
});
```

### Error Handling Middleware

```javascript
app.get('/data', (req, res, next) => {
  try {
    throw new Error('Something went wrong');
  } catch (error) {
    next(error); // Pass to error handler
  }
});

// Error handling middleware (must have 4 parameters)
app.use((err, req, res, next) => {
  console.error(err.message);
  res.status(500).send('Server error');
});
```

### Request Timing Middleware

```javascript
app.use((req, res, next) => {
  const start = Date.now();

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

  next();
});
```

## Middleware with Parameters

Middleware factories return middleware functions:

```javascript
function logMessages(format) {
  return (req, res, next) => {
    if (format === 'simple') {
      console.log(`${req.method} ${req.url}`);
    } else if (format === 'detailed') {
      console.log(`${req.method} ${req.url} - ${req.headers['user-agent']}`);
    }
    next();
  };
}

app.use(logMessages('simple'));
// or
app.use(logMessages('detailed'));
```

## Complete Example with Multiple Middleware

```javascript
import express from 'express';

const app = express();

// Built-in middleware
app.use(express.json());

// Custom logging middleware
app.use((req, res, next) => {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
  next();
});

// Authentication middleware
function authenticate(req, res, next) {
  const token = req.query.token;
  if (token === 'secret') {
    req.user = { id: 1, name: 'John' };
    next();
  } else {
    res.status(401).send('Unauthorized');
  }
}

// Request validation middleware
function validateRequest(req, res, next) {
  if (!req.body.email) {
    return res.status(400).send('Email required');
  }
  next();
}

// Public route
app.get('/home', (req, res) => {
  res.send('Welcome');
});

// Protected route
app.get('/profile', authenticate, (req, res) => {
  res.send(`Hello ${req.user.name}`);
});

// Route with validation
app.post('/register', validateRequest, (req, res) => {
  res.send(`Registered ${req.body.email}`);
});

// Error handling middleware (must be last)
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Server error' });
});

app.listen(3000, () => {
  console.log('Server running');
});
```

## Common Mistakes

**Mistake 1: Forgetting to call** `next()`

```javascript
// Wrong - middleware stops here
app.use((req, res, next) => {
  console.log('Middleware');
  // No next() call - route never executes
});

app.get('/', (req, res) => {
  res.send('Hello'); // Never reached
});

// Right
app.use((req, res, next) => {
  console.log('Middleware');
  next(); // Passes to next handler
});
```

**Mistake 2: Wrong middleware order**

```javascript
// Wrong - middleware after route can't help
app.get('/', (req, res) => {
  res.send(req.body); // undefined - JSON not parsed yet
});

app.use(express.json()); // Too late!

// Right - middleware before routes
app.use(express.json());
app.get('/', (req, res) => {
  res.send(req.body); // Properly parsed
});
```

**Mistake 3: Error handler must have 4 parameters**

```javascript
// Wrong - Express won't recognize as error handler
app.use((err, req, res) => {
  res.send('Error');
});

// Right - all 4 parameters required
app.use((err, req, res, next) => {
  res.send('Error');
});
```

## Key Takeaways

*   Middleware intercepts requests and can modify them or stop them
    
*   Middleware runs in the order it's defined
    
*   Call `next()` to pass to the next middleware
    
*   Express provides built-in middleware like `express.json()`
    
*   You can create custom middleware for any task
    
*   Application-level middleware runs for all/specific routes
    
*   Error handlers are middleware with 4 parameters
    
*   Order matters: define middleware before routes that need it
    

Middleware is the backbone of Express applications. Master it, and you can build clean, modular, and powerful web applications.
