fortify2-js
Version:
MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.
839 lines (836 loc) • 30.9 kB
JavaScript
import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
import compression from 'compression';
import rateLimit from 'express-rate-limit';
import { logger } from '../../../utils/Logger.js';
import { NehoID } from 'nehoid';
/**
* MiddlewareManager - Advanced middleware system with optimization, caching, and performance tracking
* Provides comprehensive middleware management withFortify FastServer (FFS)performance enhancements
*/
class MiddlewareManager {
constructor(options, dependencies) {
// Middleware registry and management
this.middlewareRegistry = new Map();
this.middlewareCache = new Map();
this.executionOrder = [];
// Performance tracking
this.performanceMetrics = {
totalRequests: 0,
totalExecutionTime: 0,
averageExecutionTime: 0,
fastestExecution: Infinity,
slowestExecution: 0,
cacheHitRate: 0,
errorRate: 0,
throughput: 0,
optimizationGain: 0,
};
// Configuration
this.optimizationConfig = {
enableCaching: true,
enableBatching: true,
enablePrioritization: true,
enablePerformanceTracking: true,
cacheWarming: true,
optimizationThreshold: 10,
maxCacheSize: 1000,
defaultTTL: 300000, // 5 minutes
};
this.initialized = false;
this.options = options;
this.dependencies = dependencies;
}
/**
* Initialize the middleware manager
*/
async initialize() {
if (this.initialized)
return;
logger.debug("middleware", "Initializing Middleware Manager...");
// Configure built-in middleware
this.configureBuiltInMiddleware();
// Configure optimization middleware
this.configureOptimizationMiddleware();
// Configure request processing middleware
this.configureRequestProcessingMiddleware();
// Warm up cache if enabled
if (this.optimizationConfig.cacheWarming) {
await this.warmCache();
}
this.initialized = true;
logger.debug("middleware", " Middleware Manager initialized");
}
/**
* Register custom middleware
*/
register(middleware, options) {
const id = NehoID.generate({ prefix: "ufs.middleware", size: 16 });
const name = options?.name || `middleware-${id.slice(0, 8)}`;
let handler;
let priority = options?.priority || "normal";
let routes = options?.routes;
let cacheable = options?.cacheable === true; // Only cache if explicitly set to true
let ttl = options?.ttl || this.optimizationConfig.defaultTTL;
if (typeof middleware === "function") {
handler = middleware;
}
else {
handler = middleware.handler;
priority = middleware.priority || priority;
routes = middleware.routes || routes;
cacheable = middleware.cacheable || cacheable;
ttl = middleware.ttl || ttl;
}
const entry = {
id,
name,
handler: this.wrapMiddleware(handler, name),
priority,
order: this.calculateOrder(priority),
routes,
enabled: true,
cacheable,
ttl,
metadata: {},
stats: {
executionCount: 0,
totalExecutionTime: 0,
averageExecutionTime: 0,
cacheHits: 0,
cacheMisses: 0,
errors: 0,
},
};
this.middlewareRegistry.set(id, entry);
this.updateExecutionOrder();
// Apply middleware to Express app immediately
this.applyMiddlewareToApp(entry);
logger.debug("middleware", `Registered middleware: ${name} (${id})`);
return id;
}
/**
* Unregister middleware
*/
unregister(id) {
const entry = this.middlewareRegistry.get(id);
if (!entry)
return false;
this.middlewareRegistry.delete(id);
this.updateExecutionOrder();
logger.debug("middleware", `Unregistered middleware: ${entry.name} (${id})`);
return true;
}
/**
* Enable middleware
*/
enable(id) {
const entry = this.middlewareRegistry.get(id);
if (!entry)
return false;
entry.enabled = true;
this.updateExecutionOrder();
logger.debug("middleware", `Enabled middleware: ${entry.name} (${id})`);
return true;
}
/**
* Disable middleware
*/
disable(id) {
const entry = this.middlewareRegistry.get(id);
if (!entry)
return false;
entry.enabled = false;
this.updateExecutionOrder();
logger.debug("middleware", `Disabled middleware: ${entry.name} (${id})`);
return true;
}
/**
* Enable security middleware
*/
enableSecurity(options) {
if (this.options.security?.helmet !== false) {
try {
this.dependencies.app.use(helmet(options?.helmet));
logger.debug("middleware", "Security headers (Helmet) enabled");
}
catch (error) {
logger.warn("middleware", "Helmet not available, skipping security headers");
}
}
if (this.options.security?.cors !== false) {
try {
this.dependencies.app.use(cors(options?.cors));
logger.debug("middleware", "CORS enabled");
}
catch (error) {
logger.warn("middleware", "CORS not available, skipping CORS headers");
}
}
}
/**
* Enable compression middleware
*/
enableCompression(options) {
if (this.options.performance?.compression !== false) {
try {
this.dependencies.app.use(compression(options));
logger.debug("middleware", "Compression enabled");
}
catch (error) {
logger.warn("middleware", "Compression not available, skipping compression");
}
}
}
/**
* Enable rate limiting middleware
*/
enableRateLimit(options) {
if (this.options.security?.rateLimit !== false) {
try {
const rateLimitOptions = {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
standardHeaders: true,
legacyHeaders: false,
...options,
};
this.dependencies.app.use(rateLimit(rateLimitOptions));
logger.debug("middleware", "Rate limiting enabled");
}
catch (error) {
logger.warn("middleware", "Rate limiting not available, skipping rate limiting");
}
}
}
/**
* Enable CORS middleware
*/
enableCors(options) {
try {
this.dependencies.app.use(cors(options));
logger.debug("middleware", "CORS enabled");
}
catch (error) {
logger.warn("middleware", "CORS not available, skipping CORS headers");
}
}
/**
* Get middleware information
*/
getInfo(id) {
if (id) {
const entry = this.middlewareRegistry.get(id);
if (!entry)
throw new Error(`Middleware not found: ${id}`);
return this.entryToInfo(entry);
}
return Array.from(this.middlewareRegistry.values()).map((entry) => this.entryToInfo(entry));
}
/**
* Get middleware statistics
*/
getStats() {
const entries = Array.from(this.middlewareRegistry.values());
const enabledCount = entries.filter((e) => e.enabled).length;
const byPriority = entries.reduce((acc, entry) => {
acc[entry.priority] = (acc[entry.priority] || 0) + 1;
return acc;
}, {});
const byType = entries.reduce((acc, entry) => {
acc[entry.name] = this.entryToInfo(entry);
return acc;
}, {});
return {
totalMiddleware: entries.length,
enabledMiddleware: enabledCount,
totalExecutions: this.performanceMetrics.totalRequests,
averageExecutionTime: this.performanceMetrics.averageExecutionTime,
cacheHitRate: this.performanceMetrics.cacheHitRate,
optimizationRate: this.performanceMetrics.optimizationGain,
byPriority,
byType,
performance: {
fastestMiddleware: this.findFastestMiddleware(),
slowestMiddleware: this.findSlowestMiddleware(),
mostUsedMiddleware: this.findMostUsedMiddleware(),
cacheEfficiency: this.calculateCacheEfficiency(),
},
};
}
/**
* Get performance metrics
*/
getPerformanceMetrics() {
return { ...this.performanceMetrics };
}
/**
* Optimize middleware execution
*/
async optimize() {
logger.debug("middleware", "Optimizing middleware execution...");
// Reorder middleware based on performance data
this.optimizeExecutionOrder();
// Clean up cache
this.cleanupCache();
// Update optimization metrics
this.updateOptimizationMetrics();
logger.debug("middleware", "Middleware optimization completed");
}
/**
* Warm up middleware cache
*/
async warmCache() {
logger.debug("middleware", "Warming up middleware cache...");
// Pre-cache common middleware results
const commonPaths = ["/health", "/ping", "/status"];
const commonMethods = ["GET", "POST"];
for (const path of commonPaths) {
for (const method of commonMethods) {
const cacheKey = `${method}:${path}`;
// Pre-populate cache with empty results for faster lookup
this.middlewareCache.set(cacheKey, {
result: null,
timestamp: Date.now(),
ttl: this.optimizationConfig.defaultTTL,
hits: 0,
middleware: "warmup",
});
}
}
logger.debug("middleware", "Middleware cache warmed up");
}
/**
* Clear middleware cache
*/
clearCache() {
this.middlewareCache.clear();
logger.debug("middleware", "Middleware cache cleared");
}
/**
* Execute middleware chain
*/
async executeMiddleware(req, res, next) {
const startTime = performance.now();
try {
// Get applicable middleware for this request
const applicableMiddleware = this.matchRoute(req.path, req.method);
// Execute middleware in priority order
for (const entry of applicableMiddleware) {
if (!entry.enabled)
continue;
const middlewareStartTime = performance.now();
try {
await this.executeMiddlewareEntry(entry, req, res, next);
const executionTime = performance.now() - middlewareStartTime;
this.updateMiddlewareStats(entry, executionTime, false);
}
catch (error) {
const executionTime = performance.now() - middlewareStartTime;
this.updateMiddlewareStats(entry, executionTime, true);
throw error;
}
}
const totalExecutionTime = performance.now() - startTime;
this.updatePerformanceMetrics(totalExecutionTime, false);
}
catch (error) {
const totalExecutionTime = performance.now() - startTime;
this.updatePerformanceMetrics(totalExecutionTime, true);
throw error;
}
}
/**
* Match middleware to route
*/
matchRoute(path, method) {
return this.executionOrder
.map((id) => this.middlewareRegistry.get(id))
.filter((entry) => {
if (!entry || !entry.enabled)
return false;
// If no routes specified, apply to all routes
if (!entry.routes || entry.routes.length === 0)
return true;
// Check if path matches any of the specified routes
return entry.routes.some((route) => {
if (typeof route === "string") {
return path === route || path.startsWith(route);
}
return false;
});
});
}
/**
* Configure middleware
*/
configure(config) {
this.options.middleware = { ...this.options.middleware, ...config };
// Apply configuration changes
if (config.enableOptimization !== undefined) {
this.optimizationConfig.enableCaching = config.enableOptimization;
}
if (config.enableCaching !== undefined) {
this.optimizationConfig.enableCaching = config.enableCaching;
}
if (config.enablePerformanceTracking !== undefined) {
this.optimizationConfig.enablePerformanceTracking =
config.enablePerformanceTracking;
}
logger.debug("middleware", "Middleware configuration updated");
}
/**
* Get current configuration
*/
getConfiguration() {
return { ...this.options.middleware };
}
/**
* Clear all middleware
*/
clear() {
this.middlewareRegistry.clear();
this.middlewareCache.clear();
this.executionOrder = [];
logger.debug("middleware", "All middleware cleared");
}
/**
* Create cache middleware for route optimization
*/
createCacheMiddleware(options) {
const ttl = options?.ttl || this.optimizationConfig.defaultTTL;
const keyGenerator = options?.keyGenerator ||
((req) => `${req.method}:${req.path}`);
return (req, res, next) => {
const cacheKey = keyGenerator(req);
const cached = this.middlewareCache.get(cacheKey);
if (cached && this.isCacheValid(cached)) {
cached.hits++;
logger.debug("middleware", `Cache hit for route: ${cacheKey}`);
return next();
}
// Cache miss - continue with normal processing
const originalSend = res.send;
const self = this;
res.send = function (body) {
// Cache the response
self.middlewareCache.set(cacheKey, {
result: body,
timestamp: Date.now(),
ttl,
hits: 0,
middleware: "route-cache",
});
return originalSend.call(this, body);
};
next();
};
}
/**
* Shutdown middleware manager
*/
async shutdown() {
logger.debug("middleware", "Shutting down Middleware Manager...");
this.middlewareRegistry.clear();
this.middlewareCache.clear();
this.executionOrder = [];
this.initialized = false;
logger.debug("middleware", " Middleware Manager shut down");
}
// ===== PRIVATE METHODS =====
/**
* Apply middleware to Express app
*/
applyMiddlewareToApp(entry) {
if (!entry.enabled)
return;
// If routes are specified, apply middleware only to those routes
if (entry.routes && entry.routes.length > 0) {
entry.routes.forEach((route) => {
this.dependencies.app.use(route, entry.handler);
logger.debug("middleware", `Applied middleware "${entry.name}" to route: ${route}`);
});
}
else {
// Apply to all routes
this.dependencies.app.use(entry.handler);
logger.debug("middleware", `Applied middleware "${entry.name}" globally`);
}
}
/**
* Configure built-in middleware
*/
configureBuiltInMiddleware() {
logger.debug("middleware", "Configuring built-in middleware...");
this.configureTrustProxy();
this.configureSecurityMiddleware();
this.configurePerformanceMiddleware();
this.configureBodyParsing();
logger.debug("middleware", "Built-in middleware configured");
}
/**
* Configure trust proxy settings
*/
configureTrustProxy() {
if (this.options.server?.trustProxy) {
this.dependencies.app.set("trust proxy", true);
}
}
/**
* Configure security middleware
*/
configureSecurityMiddleware() {
if (this.options.security?.helmet) {
this.enableSecurity();
}
}
/**
* Configure performance middleware
*/
configurePerformanceMiddleware() {
if (this.options.performance?.compression) {
this.enableCompression();
}
}
/**
* Configure body parsing middleware
*/
configureBodyParsing() {
this.dependencies.app.use(express.json({
limit: this.options.server?.jsonLimit,
}));
this.dependencies.app.use(express.urlencoded({
extended: true,
limit: this.options.server?.urlEncodedLimit,
}));
}
/**
* Configure optimization middleware
*/
configureOptimizationMiddleware() {
// This will be handled by the existing MiddlewareManager for now
// to maintain backward compatibility
}
/**
* Configure request processing middleware
*/
configureRequestProcessingMiddleware() {
this.dependencies.app.use(async (req, res, next) => {
// Start performance measurement
const requestId = this.dependencies.performanceProfiler.startMeasurement(req);
req.requestId = requestId;
req.startTime = performance.now();
try {
// Execute middleware chain
await this.executeMiddleware(req, res, next);
// Classify request for optimal execution path
const classification = this.dependencies.executionPredictor.classify(req);
this.dependencies.performanceProfiler.setRequestType(requestId, classification.type, classification.executionPath);
// Update optimization stats
this.dependencies.optimizationStats.totalRequests++;
if (classification.type === "ultra-fast") {
this.dependencies.optimizationStats.ultraFastRequests++;
}
else if (classification.type === "fast") {
this.dependencies.optimizationStats.fastRequests++;
}
else {
this.dependencies.optimizationStats.standardRequests++;
}
// Route to appropriate execution path
if (classification.type === "ultra-fast" &&
this.dependencies.optimizationEnabled) {
return await this.dependencies.handleUltraFastPath(req, res, next, requestId, classification);
}
else if (classification.type === "fast" &&
this.dependencies.optimizationEnabled) {
return await this.dependencies.handleFastPath(req, res, next, requestId, classification);
}
else {
return await this.dependencies.handleStandardPath(req, res, next, requestId, classification);
}
}
catch (optimizationError) {
// Graceful fallback to standard path on optimization failure
logger.warn("middleware", `Optimization failed for ${req.method} ${req.path}:`, optimizationError.message);
this.dependencies.optimizationStats.optimizationFailures++;
return await this.dependencies.handleStandardPath(req, res, next, requestId, {
type: "standard",
confidence: 1.0,
executionPath: "fallback",
cacheStrategy: "standard",
skipMiddleware: [],
reason: "Optimization failure fallback",
overhead: 0,
});
}
});
}
/**
* Wrap middleware with performance tracking and caching
*/
wrapMiddleware(handler, name) {
return async (req, res, next) => {
const startTime = performance.now();
try {
// Check cache if middleware is cacheable AND the specific middleware entry allows caching
const cacheKey = this.generateCacheKey(req, name);
const middlewareEntry = Array.from(this.middlewareRegistry.values()).find((entry) => entry.name === name);
if (this.optimizationConfig.enableCaching &&
middlewareEntry?.cacheable === true) {
const cached = this.middlewareCache.get(cacheKey);
if (cached && this.isCacheValid(cached)) {
cached.hits++;
const executionTime = performance.now() - startTime;
logger.debug("middleware", `Cache hit for ${name}: ${executionTime}ms`);
return next();
}
}
// Execute middleware (Express middleware uses callbacks, not promises)
handler(req, res, (error) => {
const executionTime = performance.now() - startTime;
if (error) {
logger.error("middleware", `Error in ${name}: ${error} (${executionTime}ms)`);
return next(error);
}
// Cache result if applicable
if (this.optimizationConfig.enableCaching &&
executionTime < 10) {
this.middlewareCache.set(cacheKey, {
result: null,
timestamp: Date.now(),
ttl: this.optimizationConfig.defaultTTL,
hits: 0,
middleware: name,
});
}
logger.debug("middleware", `Executed ${name}: ${executionTime}ms`);
next();
});
}
catch (error) {
const executionTime = performance.now() - startTime;
logger.error("middleware", `Error in ${name}: ${error} (${executionTime}ms)`);
next(error);
}
};
}
/**
* Calculate execution order based on priority
*/
calculateOrder(priority) {
const priorityOrder = {
critical: 1000,
high: 800,
normal: 500,
low: 200,
};
return priorityOrder[priority] + Math.random() * 100; // Add randomness for same priority
}
/**
* Update execution order based on priority and performance
*/
updateExecutionOrder() {
this.executionOrder = Array.from(this.middlewareRegistry.entries())
.filter(([_, entry]) => entry.enabled)
.sort(([_, a], [__, b]) => b.order - a.order)
.map(([id, _]) => id);
}
/**
* Execute a single middleware entry
*/
async executeMiddlewareEntry(entry, req, res, next) {
return new Promise((resolve, reject) => {
try {
entry.handler(req, res, (error) => {
if (error) {
reject(error);
}
else {
resolve();
}
});
}
catch (error) {
reject(error);
}
});
}
/**
* Update middleware statistics
*/
updateMiddlewareStats(entry, executionTime, hasError) {
entry.stats.executionCount++;
entry.stats.totalExecutionTime += executionTime;
entry.stats.averageExecutionTime =
entry.stats.totalExecutionTime / entry.stats.executionCount;
entry.stats.lastExecuted = new Date();
if (hasError) {
entry.stats.errors++;
}
}
/**
* Update performance metrics
*/
updatePerformanceMetrics(executionTime, hasError) {
this.performanceMetrics.totalRequests++;
this.performanceMetrics.totalExecutionTime += executionTime;
this.performanceMetrics.averageExecutionTime =
this.performanceMetrics.totalExecutionTime /
this.performanceMetrics.totalRequests;
if (executionTime < this.performanceMetrics.fastestExecution) {
this.performanceMetrics.fastestExecution = executionTime;
}
if (executionTime > this.performanceMetrics.slowestExecution) {
this.performanceMetrics.slowestExecution = executionTime;
}
if (hasError) {
this.performanceMetrics.errorRate =
(this.performanceMetrics.errorRate *
(this.performanceMetrics.totalRequests - 1) +
1) /
this.performanceMetrics.totalRequests;
}
// Calculate cache hit rate
const totalCacheAttempts = Array.from(this.middlewareCache.values()).reduce((sum, entry) => sum + entry.hits, 0);
this.performanceMetrics.cacheHitRate =
totalCacheAttempts / this.performanceMetrics.totalRequests;
// Calculate throughput (requests per second)
const now = Date.now();
this.performanceMetrics.throughput =
this.performanceMetrics.totalRequests /
((now - (now - this.performanceMetrics.totalExecutionTime)) / 1000);
}
/**
* Convert registry entry to middleware info
*/
entryToInfo(entry) {
return {
name: entry.name,
priority: entry.priority,
enabled: entry.enabled,
order: entry.order,
routes: entry.routes,
executionCount: entry.stats.executionCount,
averageExecutionTime: entry.stats.averageExecutionTime,
lastExecuted: entry.stats.lastExecuted,
cacheEnabled: entry.cacheable,
optimized: entry.stats.averageExecutionTime < 5, // Consider optimized if < 5ms
};
}
/**
* Generate cache key for middleware
*/
generateCacheKey(req, middlewareName) {
return `middleware:${middlewareName}:${req.method}:${req.path}`;
}
/**
* Check if cache entry is valid
*/
isCacheValid(entry) {
return Date.now() - entry.timestamp < entry.ttl;
}
/**
* Optimize execution order based on performance data
*/
optimizeExecutionOrder() {
// Sort by average execution time (fastest first) within same priority
this.executionOrder = Array.from(this.middlewareRegistry.entries())
.filter(([_, entry]) => entry.enabled)
.sort(([_, a], [__, b]) => {
// First by priority
if (a.priority !== b.priority) {
return b.order - a.order;
}
// Then by performance (faster first)
return (a.stats.averageExecutionTime - b.stats.averageExecutionTime);
})
.map(([id, _]) => id);
}
/**
* Clean up expired cache entries
*/
cleanupCache() {
const now = Date.now();
for (const [key, entry] of this.middlewareCache.entries()) {
if (now - entry.timestamp > entry.ttl) {
this.middlewareCache.delete(key);
}
}
// Limit cache size
if (this.middlewareCache.size > this.optimizationConfig.maxCacheSize) {
const entries = Array.from(this.middlewareCache.entries()).sort(([_, a], [__, b]) => a.hits - b.hits); // Remove least used first
const toRemove = this.middlewareCache.size -
this.optimizationConfig.maxCacheSize;
for (let i = 0; i < toRemove; i++) {
this.middlewareCache.delete(entries[i][0]);
}
}
}
/**
* Update optimization metrics
*/
updateOptimizationMetrics() {
const totalMiddleware = this.middlewareRegistry.size;
const optimizedMiddleware = Array.from(this.middlewareRegistry.values()).filter((entry) => entry.stats.averageExecutionTime < 5).length;
this.performanceMetrics.optimizationGain =
totalMiddleware > 0
? (optimizedMiddleware / totalMiddleware) * 100
: 0;
}
/**
* Find fastest middleware
*/
findFastestMiddleware() {
let fastest = "";
let fastestTime = Infinity;
for (const entry of this.middlewareRegistry.values()) {
if (entry.stats.averageExecutionTime < fastestTime) {
fastestTime = entry.stats.averageExecutionTime;
fastest = entry.name;
}
}
return fastest;
}
/**
* Find slowest middleware
*/
findSlowestMiddleware() {
let slowest = "";
let slowestTime = 0;
for (const entry of this.middlewareRegistry.values()) {
if (entry.stats.averageExecutionTime > slowestTime) {
slowestTime = entry.stats.averageExecutionTime;
slowest = entry.name;
}
}
return slowest;
}
/**
* Find most used middleware
*/
findMostUsedMiddleware() {
let mostUsed = "";
let mostUsedCount = 0;
for (const entry of this.middlewareRegistry.values()) {
if (entry.stats.executionCount > mostUsedCount) {
mostUsedCount = entry.stats.executionCount;
mostUsed = entry.name;
}
}
return mostUsed;
}
/**
* Calculate cache efficiency
*/
calculateCacheEfficiency() {
const totalCacheAttempts = Array.from(this.middlewareCache.values()).reduce((sum, entry) => sum + entry.hits, 0);
const totalRequests = this.performanceMetrics.totalRequests;
return totalRequests > 0
? (totalCacheAttempts / totalRequests) * 100
: 0;
}
}
export { MiddlewareManager };
//# sourceMappingURL=middlewareManager.js.map