UNPKG

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.

154 lines (151 loc) 5.59 kB
import { expressStringify } from '../../../components/fortified-function/serializer/safe-serializer.js'; import { logger } from '../server/utils/Logger.js'; /** * Safe JSON Middleware for Express * Automatically handles circular references in JSON responses */ /** * Creates middleware that safely handles JSON serialization */ function createSafeJsonMiddleware(options = {}) { const opts = { enabled: true, maxDepth: 10, truncateStrings: 1000, includeNonEnumerable: false, logCircularRefs: false, customReplacer: undefined, ...options, }; return function safeJsonMiddleware(req, res, next) { if (!opts.enabled) { return next(); } // Store the original json method const originalJson = res.json.bind(res); const originalSend = res.send.bind(res); // Override res.json to use safe serialization res.json = function (obj) { try { // Try standard JSON.stringify first for performance const standardResult = JSON.stringify(obj); return originalJson(obj); } catch (error) { if (opts.logCircularRefs && error.message.includes("circular")) { logger.debug("server", "🔄 Circular reference detected, using safe serialization:", { url: req.url, method: req.method, error: error.message, }); } try { // Use our safe serialization const safeResult = expressStringify(obj); const parsedResult = JSON.parse(safeResult); return originalJson(parsedResult); } catch (safeError) { logger.debug("server", "❌ Safe JSON serialization failed:", safeError); return originalJson({ error: "Serialization failed", message: "Unable to serialize response object", originalError: safeError.message, }); } } }; // Override res.send to handle objects that might be passed directly res.send = function (body) { if (typeof body === "object" && body !== null && !Buffer.isBuffer(body)) { // If it's an object, use our safe json method return res.json(body); } return originalSend(body); }; next(); }; } /** * Quick setup function for common use cases */ function setupSafeJson(app, options = {}) { app.use(createSafeJsonMiddleware(options)); } /** * Utility function to safely stringify any object */ function safeJsonStringify(obj, options = {}) { try { return JSON.stringify(obj); } catch (error) { return expressStringify(obj); } } /** * Enhanced res.json replacement that can be used manually */ function sendSafeJson(res, obj, options = {}) { try { const result = safeJsonStringify(obj, options); res.setHeader("Content-Type", "application/json"); res.send(result); } catch (error) { console.error("❌ Failed to send safe JSON:", error); res.status(500).json({ error: "Internal Server Error", message: "Failed to serialize response", }); } } /** * Middleware specifically for debugging circular references */ function createCircularRefDebugger() { return function circularRefDebugger(req, res, next) { const originalJson = res.json.bind(res); res.json = function (obj) { try { JSON.stringify(obj); return originalJson(obj); } catch (error) { if (error.message.includes("circular")) { console.log("🔍 Circular Reference Debug Info:"); console.log(" Route:", req.method, req.url); console.log(" Object type:", typeof obj); console.log(" Object constructor:", obj?.constructor?.name); console.log(" Object keys:", Object.keys(obj || {})); // Try to identify the circular reference const seen = new WeakSet(); const findCircular = (obj, path = []) => { if (typeof obj !== "object" || obj === null) return []; if (seen.has(obj)) return path; seen.add(obj); for (const [key, value] of Object.entries(obj)) { const result = findCircular(value, [...path, key]); if (result.length > 0) return result; } return []; }; const circularPath = findCircular(obj); if (circularPath.length > 0) { console.log(" Circular path:", circularPath.join(" -> ")); } } throw error; } }; next(); }; } export { createCircularRefDebugger, createSafeJsonMiddleware, safeJsonStringify, sendSafeJson, setupSafeJson }; //# sourceMappingURL=safe-json-middleware.js.map