Middleware Architecture

Overview

XyPriss uses a clean, layered middleware architecture with a single source of truth for all middleware implementations.

Architecture Layers

┌─────────────────────────────────────────────────┐
│         User Configuration (config.ts)          │
│    ServerOptions.security.cors, helmet, etc.    │
└────────────────┬────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────┐
│        SecurityMiddleware (Orchestrator)        │
│   - Reads SecurityConfig from ServerOptions     │
│   - Applies security logic and policies         │
│   - Delegates to BuiltInMiddleware              │
└────────────────┬────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────┐
│   BuiltInMiddleware (Single Source of Truth)    │
│   - Wraps external libraries (cors, helmet)     │
│   - Provides consistent defaults                │
│   - Handles all middleware initialization       │
└────────────────┬────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────┐
│      External Libraries (cors, helmet, etc.)    │
└─────────────────────────────────────────────────┘

Key Principles

1. Single Source of Truth

BuiltInMiddleware is the ONLY place that imports external middleware libraries:

  • cors
  • helmet
  • express-rate-limit
  • compression
  • hpp
  • express-mongo-sanitize
  • csrf-csrf
  • multer

2. No Duplicate Imports

NEVER import middleware libraries directly in other files ✅ ALWAYS use BuiltInMiddleware.cors(), BuiltInMiddleware.helmet(), etc.

3. Clear Separation of Concerns

BuiltInMiddleware (src/middleware/built-in/BuiltInMiddleware.ts)

  • Purpose: Wrapper layer for external libraries
  • Responsibility: Provide consistent defaults and interfaces
  • Example:
static cors(options: any = {}) {
    const defaultOptions = {
        origin: true,
        methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
        credentials: false,
        maxAge: 86400,
    };
    return cors({ ...defaultOptions, ...options });
}

SecurityMiddleware (src/middleware/security-middleware.ts)

  • Purpose: Security orchestration and policy enforcement
  • Responsibility: Apply security configurations and combine middleware
  • Example:
private initializeMiddleware(): void {
    if (this.cors !== false) {
        this.corsMiddleware = BuiltInMiddleware.cors(corsConfig);
    }
}

Configuration Flow

1. User Configuration

// config.ts
export const config = {
    security: {
        enabled: true,
        cors: {
            origin: "*",
            methods: ["GET", "POST"],
            allowedHeaders: ["Content-Type", "Authorization"],
            credentials: true,
        },
    },
};

2. Server Initialization

// ServerFactory.ts → FastServer.ts
const server = new XyPrissServer(options);
// FastServer.initializeSecurity() creates SecurityMiddleware

3. SecurityMiddleware Initialization

// SecurityMiddleware constructor
this.cors = config.cors !== false ? (config.cors || true) : false;
this.initializeMiddleware();

4. BuiltInMiddleware Usage

// SecurityMiddleware.initializeMiddleware()
this.corsMiddleware = BuiltInMiddleware.cors(corsConfig);

5. Middleware Application

// SecurityMiddleware.applySecurityStack()
if (this.cors !== false && this.corsMiddleware) {
    middlewareStack.push(this.corsMiddleware);
}

Multi-Server Mode

In multi-server mode, security configuration is properly deep-merged:

// MultiServerManager.mergeServerConfig()
merged.security = {
    ...merged.security,
    ...serverConfig.security,
    // Deep merge CORS config
    cors: serverConfig.security.cors !== undefined
        ? (typeof serverConfig.security.cors === 'object' && 
           typeof merged.security?.cors === 'object'
            ? { ...merged.security.cors, ...serverConfig.security.cors }
            : serverConfig.security.cors)
        : merged.security?.cors
};

Benefits

✅ Maintainability

  • Single place to update middleware wrappers
  • Easy to add new middleware
  • Clear dependency management

✅ Consistency

  • All middleware uses same configuration pattern
  • Consistent defaults across the application
  • Predictable behavior

✅ Testability

  • Easy to mock BuiltInMiddleware
  • Clear interfaces for testing
  • Isolated concerns

✅ Developer Experience

  • Simple, intuitive configuration
  • Type-safe with TypeScript
  • Clear documentation

Adding New Middleware

To add new middleware to the system:

  1. Add to BuiltInMiddleware:
// src/middleware/built-in/BuiltInMiddleware.ts
static newMiddleware(options: any = {}) {
    const defaultOptions = { /* defaults */ };
    return externalLibrary({ ...defaultOptions, ...options });
}
  1. Update SecurityConfig (if security-related):
// src/types/mod/security.ts
export interface SecurityConfig {
    // ... existing fields
    newFeature?: boolean | NewFeatureConfig;
}
  1. Use in SecurityMiddleware:
// src/middleware/security-middleware.ts
if (this.newFeature) {
    this.newFeatureMiddleware = BuiltInMiddleware.newMiddleware(config);
}

Migration Guide

If you find code that imports middleware libraries directly:

❌ Before (Bad)

import cors from 'cors';
import helmet from 'helmet';

const corsMiddleware = cors({ origin: "*" });

✅ After (Good)

import { BuiltInMiddleware } from './built-in/BuiltInMiddleware';

const corsMiddleware = BuiltInMiddleware.cors({ origin: "*" });

Summary

The refactored architecture provides:

  • Single Source of Truth: BuiltInMiddleware
  • Clean Separation: Configuration → Security → BuiltIn → External
  • Easy Maintenance: One place to update
  • Type Safety: Full TypeScript support
  • Developer Friendly: Simple, intuitive API