---
name: middleware-patterns
description: Express middleware patterns and best practices for GoodGo microservices. Use when creating custom middleware, organizing middleware chains, handling request/response transformation, or implementing cross-cutting concerns.
---

# Middleware Patterns

## When to Use This Skill

Use this skill when:
- Creating custom Express middleware
- Organizing middleware chains and ordering
- Implementing authentication/authorization middleware
- Creating request/response transformation middleware
- Handling cross-cutting concerns (logging, metrics, validation)
- Implementing async middleware patterns
- Testing middleware implementations

## Core Concepts

### Middleware Function Signature

Express middleware functions have this signature:

```typescript
(req: Request, res: Response, next: NextFunction) => void | Promise<void>
```

### Middleware Types

1. **Application-level**: Applied to all routes (`app.use()`)
2. **Router-level**: Applied to specific routes (`router.use()`)
3. **Route-level**: Applied to specific route handlers

### Middleware Execution Order

**Critical**: Middleware order matters! Execution flows top-to-bottom:

```
Request → Middleware 1 → Middleware 2 → ... → Route Handler → Response
```

The following diagram illustrates the complete middleware chain flow in GoodGo services:

```mermaid
flowchart TD
    Start([HTTP Request]) --> Security["Security Middleware<br/>Helmet, CORS"]
    Security --> RateLimit["Rate Limiting<br/>Middleware"]
    RateLimit --> Correlation["Correlation ID<br/>Middleware"]
    Correlation --> BodyParsing["Body Parsing<br/>JSON, URLEncoded, Cookies"]
    BodyParsing --> Logging["Request Logging<br/>Middleware"]
    Logging --> Metrics["Metrics Collection<br/>Middleware"]
    Metrics --> Routes["Route Handlers"]
    Routes -->|Success| Response([HTTP Response])
    Routes -->|Error| ErrorHandler["Error Handler<br/>Middleware"]
    Routes -->|Not Found| NotFound["Not Found<br/>Handler"]
    ErrorHandler --> Response
    NotFound --> Response
```

## Patterns

### Middleware Chain Order

Standard middleware order in GoodGo services:

```typescript
// 1. Security (Helmet, CORS)
app.use(helmet());
app.use(cors({ ... }));

// 2. Rate Limiting
app.use('/api', rateLimitMiddleware);

// 3. Correlation ID (early for tracing)
app.use(correlationMiddleware());

// 4. Body Parsing
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());

// 5. Request Logging
app.use(loggerMiddleware);

// 6. Metrics
app.use(metricsMiddleware);

// 7. Routes
app.use(createRouter());

// 8. Error Handling (ALWAYS LAST)
app.use(notFoundHandler);
app.use(errorHandler);
```

### Correlation Middleware Pattern

Adds correlation ID for request tracing:

```typescript
export const correlationMiddleware = () => {
  return (req: Request, res: Response, next: NextFunction) => {
    const correlationId = req.headers['x-correlation-id'] || generateId();
    req.correlationId = correlationId;
    res.setHeader('x-correlation-id', correlationId);
    next();
  };
};
```

### Authentication Middleware Pattern

Verifies JWT tokens and attaches user to request:

```typescript
export const authenticate = () => {
  return async (req: Request, res: Response, next: NextFunction) => {
    try {
      const token = extractToken(req);
      if (!token) {
        return res.status(401).json({ error: 'Unauthorized' });
      }
      
      const payload = await jwtService.verify(token);
      req.user = payload;
      next();
    } catch (error) {
      return res.status(401).json({ error: 'Invalid token' });
    }
  };
};
```

The following sequence diagram illustrates the authentication middleware flow:

```mermaid
sequenceDiagram
    participant Client
    participant AuthMW as Authentication Middleware
    participant JWTService as JWT Service
    participant RouteHandler as Route Handler
    
    Client->>AuthMW: HTTP Request with Token
    AuthMW->>AuthMW: Extract token from headers
    alt Token exists
        AuthMW->>JWTService: Verify token
        alt Token valid
            JWTService-->>AuthMW: Payload (user data)
            AuthMW->>AuthMW: Attach user to req.user
            AuthMW->>RouteHandler: next() - Continue
            RouteHandler->>Client: HTTP Response (200)
        else Token invalid
            JWTService-->>AuthMW: Verification error
            AuthMW->>Client: HTTP Response (401 Unauthorized)
        end
    else No token
        AuthMW->>Client: HTTP Response (401 Unauthorized)
    end
```

### Validation Middleware Pattern

Validates request data using Zod:

```typescript
export const validateDto = (schema: AnyZodObject, property: 'body' | 'query' | 'params' = 'body') => {
  return (req: Request, res: Response, next: NextFunction) => {
    try {
      const validatedData = schema.parse(req[property]);
      (req as any)[property] = validatedData;
      next();
    } catch (error) {
      if (error instanceof ZodError) {
        return res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            details: error.errors,
          },
        });
      }
      next(error);
    }
  };
};
```

The following sequence diagram shows the validation middleware flow:

```mermaid
sequenceDiagram
    participant Client
    participant ValidateMW as Validation Middleware
    participant ZodSchema as Zod Schema
    participant RouteHandler as Route Handler
    
    Client->>ValidateMW: HTTP Request with Data
    ValidateMW->>ValidateMW: Extract data from req[property]
    ValidateMW->>ZodSchema: schema.parse(data)
    alt Validation successful
        ZodSchema-->>ValidateMW: Validated data
        ValidateMW->>ValidateMW: Replace req[property] with validated data
        ValidateMW->>RouteHandler: next() - Continue
        RouteHandler->>Client: HTTP Response (200)
    else Validation failed
        ZodSchema-->>ValidateMW: ZodError with details
        ValidateMW->>ValidateMW: Format error response
        ValidateMW->>Client: HTTP Response (400 Validation Error)
    end
```

### Conditional Middleware

Apply middleware conditionally:

```typescript
const conditionalAuth = (options: { optional?: boolean } = {}) => {
  return async (req: Request, res: Response, next: NextFunction) => {
    try {
      const token = extractToken(req);
      if (token) {
        const payload = await jwtService.verify(token);
        req.user = payload;
      } else if (!options.optional) {
        return res.status(401).json({ error: 'Unauthorized' });
      }
      next();
    } catch (error) {
      if (!options.optional) {
        return res.status(401).json({ error: 'Invalid token' });
      }
      next();
    }
  };
};
```

### Async Middleware Pattern

Handle async operations properly:

```typescript
export const asyncMiddleware = (fn: Function) => {
  return (req: Request, res: Response, next: NextFunction) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
};

// Usage
app.get('/users', asyncMiddleware(async (req, res) => {
  const users = await userService.findAll();
  res.json({ success: true, data: users });
}));
```

The following sequence diagram illustrates async middleware error handling:

```mermaid
sequenceDiagram
    participant Client
    participant AsyncMW as Async Middleware Wrapper
    participant AsyncHandler as Async Route Handler
    participant ErrorHandler as Error Handler
    
    Client->>AsyncMW: HTTP Request
    AsyncMW->>AsyncHandler: Execute async function
    alt Async operation succeeds
        AsyncHandler->>AsyncHandler: Process request
        AsyncHandler->>Client: HTTP Response (200)
    else Async operation fails
        AsyncHandler-->>AsyncMW: Promise rejection (Error)
        AsyncMW->>ErrorHandler: next(error)
        ErrorHandler->>ErrorHandler: Format error response
        ErrorHandler->>Client: HTTP Response (500 Error)
    end
```

### Request/Response Transformation

Transform request or response data:

```typescript
export const transformResponse = () => {
  return (req: Request, res: Response, next: NextFunction) => {
    const originalJson = res.json.bind(res);
    
    res.json = function(data: any) {
      const transformed = {
        success: true,
        data,
        timestamp: new Date().toISOString(),
      };
      return originalJson(transformed);
    };
    
    next();
  };
};
```

The following sequence diagram shows how request and response transformation middleware works:

```mermaid
sequenceDiagram
    participant Client
    participant TransformMW as Transform Middleware
    participant RouteHandler as Route Handler
    participant Response as Response Object
    
    Client->>TransformMW: HTTP Request
    Note over TransformMW: Intercept res.json()
    TransformMW->>TransformMW: Store original res.json
    TransformMW->>TransformMW: Override res.json with transformation logic
    TransformMW->>RouteHandler: next() - Continue chain
    
    RouteHandler->>RouteHandler: Process request, Generate data
    RouteHandler->>Response: res.json(rawData)
    
    Note over Response: Transformed res.json executes
    Response->>Response: Wrap data: success, data, timestamp
    Response->>Client: HTTP Response (transformed)
```

### Logging Middleware Pattern

Log request details:

```typescript
export const requestLogger = (req: Request, res: Response, next: NextFunction) => {
  const startTime = Date.now();
  
  res.on('finish', () => {
    const duration = Date.now() - startTime;
    logger.info('Request completed', {
      method: req.method,
      url: req.url,
      statusCode: res.statusCode,
      duration,
      correlationId: req.correlationId,
    });
  });
  
  next();
};
```

The following sequence diagram illustrates how logging middleware tracks request lifecycle:

```mermaid
sequenceDiagram
    participant Client
    participant LogMW as Logging Middleware
    participant RouteHandler as Route Handler
    participant Logger as Logger Service
    participant Response as Response Object
    
    Client->>LogMW: HTTP Request
    LogMW->>LogMW: Record startTime = Date.now()
    LogMW->>RouteHandler: next() - Continue chain
    
    RouteHandler->>RouteHandler: Process request
    RouteHandler->>Response: res.json(data) or res.send()
    
    Response->>Response: Set statusCode, send response
    Response->>Response: Emit 'finish' event
    
    Response->>LogMW: 'finish' event triggered
    LogMW->>LogMW: Calculate duration = Date.now() - startTime
    LogMW->>Logger: logger.info('Request completed', {<br/>method, url, statusCode,<br/>duration, correlationId})
    Logger->>Logger: Write structured log entry
    
    Response->>Client: HTTP Response
```

## Best Practices

1. **Order Matters**: Place middleware in correct order (security → correlation → parsing → logging → routes → errors)
2. **Error Handling**: Always handle errors and call `next(error)` for error middleware
3. **Async Support**: Wrap async middleware properly to catch promise rejections
4. **Early Returns**: Use early returns for validation failures (don't call `next()`)
5. **Request Extension**: Use TypeScript declaration merging to extend Request type
6. **Conditional Logic**: Use middleware factories for conditional middleware
7. **Reusability**: Create reusable middleware functions
8. **Performance**: Keep middleware lightweight, avoid heavy operations

## Common Mistakes

1. **Wrong Order**: Placing middleware in incorrect order (e.g., error handler before routes)
2. **Not Calling Next**: Forgetting to call `next()` or `next(error)`
3. **Async Errors**: Not handling promise rejections in async middleware
4. **Early Return Issues**: Calling `next()` after sending response
5. **Type Safety**: Not extending Express Request type properly
6. **Performance**: Doing heavy operations in middleware

## Troubleshooting

### Middleware Not Executing

**Problem**: Middleware not being called
**Solution**: Check middleware order, ensure it's added before routes. Verify `next()` is called.

### Async Errors Not Caught

**Problem**: Unhandled promise rejections in async middleware
**Solution**: Use `asyncHandler` wrapper or wrap async code in try-catch with `next(error)`.

## Resources

- [Correlation Middleware](../../services/iam-service/src/middlewares/correlation.middleware.ts)
- [Auth Middleware](../../services/iam-service/src/middlewares/auth.middleware.ts)
- [Validation Middleware](../../services/iam-service/src/middlewares/validation.middleware.ts)
- [Error Handling](../error-handling-patterns/SKILL.md) - Error middleware patterns
