Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/juanjh1/asimilation/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Middleware types define the function signatures for middleware that runs before controllers in Asimilation. There are two middleware types: MiddlewareFunction (synchronous) and MiddlewareFunctionAsync (asynchronous).
import type { Types } from '@asimilation/core';

// Access types
type MiddlewareFunction = Types.MiddlewareFunction;
type MiddlewareFunctionAsync = Types.MiddlewareFunctionAsync;

Type Definitions

MiddlewareFunction

Synchronous middleware function for handling requests.
type MiddlewareFunction = (
  req: ArgumentedIncomingMessageAbc,
  res: ArgumentedServerResponseAbc,
  next: (error?: Error) => void
) => void
req
ArgumentedIncomingMessageAbc
Extended incoming HTTP request object with:
  • params: Record<string, string> - URL path parameters
  • All standard Node.js IncomingMessage properties
res
ArgumentedServerResponseAbc
Extended HTTP response object with helper methods:
  • sendJson(json: Object, code: number): void
  • sendText(text: string, code: number): void
  • redirect(url: string, code?: number): void
next
(error?: Error) => void
Function to call to pass control to the next middleware or controller.
  • Call next() to continue to the next middleware
  • Call next(error) to pass an error
  • Don’t call next() if you send a response
return
void
Middleware functions do not return a value.

MiddlewareFunctionAsync

Asynchronous middleware function for handling requests with async operations.
type MiddlewareFunctionAsync = (
  req: ArgumentedIncomingMessageAbc,
  res: ArgumentedServerResponseAbc,
  next: (error?: Error) => void
) => Promise<void>
The parameters are identical to MiddlewareFunction, but the function returns a Promise<void>.

Examples

Basic Logging Middleware

import { MiddlewarePipeline } from '@asimilation/core';
import type { Types } from '@asimilation/core';

const logger: Types.MiddlewareFunction = (req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
};

MiddlewarePipeline.addMiddleware(logger);

Authentication Middleware

import { MiddlewarePipeline } from '@asimilation/core';
import type { Types } from '@asimilation/core';

const authMiddleware: Types.MiddlewareFunction = (req, res, next) => {
  const token = req.headers.authorization;
  
  if (!token) {
    res.sendJson({ error: 'Unauthorized' }, 401);
    return; // Don't call next()
  }
  
  // Validate token
  if (token !== 'valid-token') {
    res.sendJson({ error: 'Invalid token' }, 401);
    return;
  }
  
  next(); // Continue to next middleware or controller
};

MiddlewarePipeline.addMiddleware(authMiddleware);

Async Database Middleware

import { MiddlewarePipeline } from '@asimilation/core';
import type { Types } from '@asimilation/core';

const dbMiddleware: Types.MiddlewareFunctionAsync = async (req, res, next) => {
  try {
    const user = await fetchUserFromDatabase();
    (req as any).user = user;
    next();
  } catch (error) {
    res.sendJson({ error: 'Database error' }, 500);
  }
};

async function fetchUserFromDatabase() {
  return { id: 1, name: 'Alice' };
}

MiddlewarePipeline.addMiddleware(dbMiddleware);

Request Timing Middleware

import type { Types } from '@asimilation/core';
import { MiddlewarePipeline } from '@asimilation/core';

const timingMiddleware: Types.MiddlewareFunction = (req, res, next) => {
  const start = Date.now();
  
  // Store original end method
  const originalEnd = res.end.bind(res);
  
  // Override end method
  res.end = function(...args: any[]) {
    const duration = Date.now() - start;
    console.log(`Request took ${duration}ms`);
    return originalEnd(...args);
  };
  
  next();
};

MiddlewarePipeline.addMiddleware(timingMiddleware);

CORS Middleware

import type { Types } from '@asimilation/core';
import { MiddlewarePipeline } from '@asimilation/core';

const corsMiddleware: Types.MiddlewareFunction = (req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  
  if (req.method === 'OPTIONS') {
    res.writeHead(204);
    res.end();
    return; // Don't call next() for OPTIONS
  }
  
  next();
};

MiddlewarePipeline.addMiddleware(corsMiddleware);

Request Body Parser

import type { Types } from '@asimilation/core';
import { MiddlewarePipeline } from '@asimilation/core';

const bodyParser: Types.MiddlewareFunctionAsync = async (req, res, next) => {
  if (req.method === 'POST' || req.method === 'PUT' || req.method === 'PATCH') {
    const chunks: Buffer[] = [];
    
    req.on('data', (chunk) => {
      chunks.push(chunk);
    });
    
    req.on('end', () => {
      const body = Buffer.concat(chunks).toString();
      
      try {
        (req as any).body = JSON.parse(body);
      } catch (error) {
        (req as any).body = body;
      }
      
      next();
    });
  } else {
    next();
  }
};

MiddlewarePipeline.addMiddleware(bodyParser);

Route-Specific Middleware

import { url } from '@asimilation/core';
import type { Types } from '@asimilation/core';

const adminOnly: Types.MiddlewareFunction = (req, res, next) => {
  const userRole = (req as any).user?.role;
  
  if (userRole !== 'admin') {
    res.sendJson({ error: 'Forbidden' }, 403);
    return;
  }
  
  next();
};

url.addPath('/admin/users', (req, res) => {
  res.sendJson({ users: [] }, 200);
}, {
  handlers: [adminOnly]
});

Error Handling Middleware

import type { Types } from '@asimilation/core';
import { MiddlewarePipeline } from '@asimilation/core';

const errorHandler: Types.MiddlewareFunction = (req, res, next) => {
  try {
    next();
  } catch (error) {
    console.error('Error caught:', error);
    res.sendJson({
      error: 'Internal server error',
      message: error instanceof Error ? error.message : 'Unknown error'
    }, 500);
  }
};

MiddlewarePipeline.addMiddleware(errorHandler);

Rate Limiting Middleware

import type { Types } from '@asimilation/core';
import { MiddlewarePipeline } from '@asimilation/core';

const requestCounts = new Map<string, { count: number; resetTime: number }>();

const rateLimiter: Types.MiddlewareFunction = (req, res, next) => {
  const ip = req.socket.remoteAddress || 'unknown';
  const now = Date.now();
  const windowMs = 60000; // 1 minute
  const maxRequests = 100;
  
  const record = requestCounts.get(ip);
  
  if (!record || now > record.resetTime) {
    requestCounts.set(ip, {
      count: 1,
      resetTime: now + windowMs
    });
    next();
    return;
  }
  
  if (record.count >= maxRequests) {
    res.sendJson({ error: 'Too many requests' }, 429);
    return;
  }
  
  record.count++;
  next();
};

MiddlewarePipeline.addMiddleware(rateLimiter);

Conditional Middleware

import type { Types } from '@asimilation/core';
import { MiddlewarePipeline } from '@asimilation/core';

const conditionalAuth: Types.MiddlewareFunction = (req, res, next) => {
  const publicPaths = ['/login', '/register', '/health', '/'];
  
  // Skip auth for public paths
  if (publicPaths.includes(req.url || '')) {
    next();
    return;
  }
  
  // Require auth for all other paths
  const token = req.headers.authorization;
  if (!token) {
    res.sendJson({ error: 'Unauthorized' }, 401);
    return;
  }
  
  next();
};

MiddlewarePipeline.addMiddleware(conditionalAuth);

Multiple Middleware Chain

import { url } from '@asimilation/core';
import type { Types } from '@asimilation/core';

const logRequest: Types.MiddlewareFunction = (req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
};

const validateAuth: Types.MiddlewareFunction = (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    res.sendJson({ error: 'Unauthorized' }, 401);
    return;
  }
  next();
};

const checkPermissions: Types.MiddlewareFunction = (req, res, next) => {
  const userRole = (req as any).user?.role;
  if (userRole !== 'admin') {
    res.sendJson({ error: 'Forbidden' }, 403);
    return;
  }
  next();
};

url.addPath('/admin/settings', (req, res) => {
  res.sendJson({ settings: {} }, 200);
}, {
  handlers: [logRequest, validateAuth, checkPermissions]
});

Middleware Execution Flow

Middleware executes in the following order:
  1. Global middleware (via MiddlewarePipeline.addMiddleware())
  2. Route-specific middleware (via PathKwargs.handlers)
  3. Controller function
import { MiddlewarePipeline, url } from '@asimilation/core';
import type { Types } from '@asimilation/core';

// 1. Global middleware
const globalMiddleware: Types.MiddlewareFunction = (req, res, next) => {
  console.log('1. Global middleware');
  next();
};

MiddlewarePipeline.addMiddleware(globalMiddleware);

// 2. Route middleware
const routeMiddleware: Types.MiddlewareFunction = (req, res, next) => {
  console.log('2. Route middleware');
  next();
};

// 3. Controller
url.addPath('/test', (req, res) => {
  console.log('3. Controller');
  res.sendJson({ success: true }, 200);
}, {
  handlers: [routeMiddleware]
});

Best Practices

Always call next() unless you’re sending a response or handling an error.
Never call next() after sending a response, as this will cause errors.
// ✓ Good: Send response and return
const goodMiddleware: Types.MiddlewareFunction = (req, res, next) => {
  if (!authorized) {
    res.sendJson({ error: 'Unauthorized' }, 401);
    return; // Don't call next()
  }
  next(); // Continue if authorized
};

// ✗ Bad: Calling next() after response
const badMiddleware: Types.MiddlewareFunction = (req, res, next) => {
  if (!authorized) {
    res.sendJson({ error: 'Unauthorized' }, 401);
    next(); // This will cause errors!
  }
};
Use async middleware for operations that involve I/O, database queries, or other asynchronous tasks.
// ✓ Good: Async middleware for async operations
const asyncMiddleware: Types.MiddlewareFunctionAsync = async (req, res, next) => {
  try {
    const data = await fetchFromDatabase();
    (req as any).data = data;
    next();
  } catch (error) {
    res.sendJson({ error: 'Database error' }, 500);
  }
};

MiddlewarePipeline

Global middleware management

PathKwargs

Route-specific middleware configuration

Controller Types

Controller function signatures