UNPKG

qgenutils

Version:

A security-first Node.js utility library providing authentication, HTTP operations, URL processing, validation, datetime formatting, and template rendering. Designed as a lightweight alternative to heavy npm packages with comprehensive error handling and

184 lines (170 loc) 8.32 kB
/* * Response Utilities Module * * This module provides centralized response handling utilities that standardize * HTTP responses across all modules. It consolidates error response patterns * and Express response validation to ensure consistent API behavior. * * DESIGN PHILOSOPHY: * - Consistency: All modules use the same response format and error handling * - Fail-fast: Invalid responses are caught early with clear error messages * - Developer experience: Centralized logging and debugging for all responses * - Security: Standardized error messages prevent information leakage * * CONSOLIDATION RATIONALE: * Previously, validation.js and http.js had duplicate response handling code. * This module eliminates that duplication while providing a single source of * truth for response formatting across the entire application. */ const { qerrors } = require('qerrors'); // error logger const logger = require('./logger'); // structured logger const { isValidObject, isValidExpressResponse } = require('./input-validation'); // response object validators /** * Send standardized JSON responses * * RATIONALE: Centralizes all JSON response logic that was previously duplicated * across validation.js and http.js. Ensures consistent response format, * proper Content-Type headers, and unified logging across all modules. * * IMPLEMENTATION DECISIONS: * - Use Express's built-in json() method for proper serialization * - Log all responses for debugging and monitoring * - Keep function simple - no transformation or complex error handling * - Validate response object to prevent runtime errors * * @param {object} res - Express response object * @param {number} statusCode - HTTP status code (200, 400, 500, etc.) * @param {object} data - Response data to be JSON-serialized */ function sendJsonResponse(res, statusCode, data) { console.log(`sendJsonResponse is sending ${statusCode} with`, data); logger.debug(`sendJsonResponse is sending ${statusCode} with`, data); // Validate response object before attempting to use it if (!isValidExpressResponse(res)) { qerrors(new Error('Invalid Express response object'), 'sendJsonResponse', { statusCode, data }); return; // Cannot send response if res object is invalid } try { res.status(statusCode); // set status code without relying on chaining res.json(data); // send JSON payload separately for non-chainable res objects } catch (error) { qerrors(error, 'sendJsonResponse', { statusCode, data }); // If JSON serialization fails, try to send a basic error response try { res.status(500); // ensure status is set even if chaining unsupported res.json({ error: 'Response serialization failed' }); // send fallback payload } catch (fallbackError) { qerrors(fallbackError, 'sendJsonResponse_fallback', { statusCode, data }); } } } /** * Send standardized validation error responses * * RATIONALE: Consolidates the validation error pattern that was duplicated * in validation.js. Provides consistent error format for all validation * failures across the application. * * DESIGN DECISIONS: * - Use 400 as default status for validation errors (client error) * - Allow additional data to be included for detailed error information * - Validate response object before attempting to send * - Use sendJsonResponse for consistency with other response types * * @param {object} res - Express response object * @param {string} message - Error message describing the validation failure * @param {object} additionalData - Optional additional data (missing fields, etc.) * @param {number} statusCode - HTTP status code (defaults to 400) */ function sendValidationError(res, message, additionalData = {}, statusCode = 400) { console.log(`sendValidationError is sending ${statusCode} with message: ${message}`); logger.debug(`sendValidationError is sending ${statusCode} with message: ${message}`); if (!isValidExpressResponse(res)) { qerrors(new Error('Invalid Express response object'), 'sendValidationError', { message, additionalData, statusCode }); return; } const errorResponse = { error: message, ...additionalData }; sendJsonResponse(res, statusCode, errorResponse); } /** * Send standardized authentication error responses * * RATIONALE: Provides consistent authentication error handling that can be * used across auth.js and other modules that need to handle authentication * failures. Centralizes the 401 response pattern. * * IMPLEMENTATION DECISIONS: * - Always use 401 status code for authentication errors (vs 403 forbidden) * - Default to generic message to avoid revealing authentication internals * - Log authentication failures for security monitoring * - Use consistent error response format across all authentication points * * SECURITY CONSIDERATIONS: * - Generic error messages prevent authentication mechanism disclosure * - 401 status triggers browser authentication prompts where appropriate * - Consistent responses prevent timing-based user enumeration attacks * * @param {object} res - Express response object * @param {string} message - Authentication error message (defaults to generic message) */ function sendAuthError(res, message = 'Authentication required') { console.log(`sendAuthError is sending 401 with message: ${message}`); logger.debug(`sendAuthError is sending 401 with message: ${message}`); // Log for security monitoring sendJsonResponse(res, 401, { error: message }); } /** * Send standardized server error responses * * RATIONALE: Provides consistent 500 error handling across all modules. * Prevents sensitive error information from leaking to clients while * ensuring proper error logging for debugging. * * IMPLEMENTATION DECISIONS: * - Always use 500 status code for internal server errors * - Send generic message to client, log detailed error internally * - Accept optional error object and context for comprehensive logging * - Use qerrors for structured error logging when available * * SECURITY CONSIDERATIONS: * - Never expose internal error details to clients (stack traces, file paths) * - Log full error context for debugging without client exposure * - Generic error messages prevent information disclosure attacks * - Detailed logging enables effective debugging without security risks * * ERROR LOGGING STRATEGY: * - Public message: Generic, safe for client consumption * - Internal logging: Detailed error object, context, and stack traces * - Structured logging: Consistent format for log analysis and monitoring * * @param {object} res - Express response object * @param {string} message - Public error message (defaults to generic message for security) * @param {Error} error - Original error object for internal logging * @param {string} context - Context information for debugging (function name, operation, etc.) */ function sendServerError(res, message = 'Internal server error', error = null, context = null) { console.log(`sendServerError is sending 500 with message: ${message}`); logger.debug(`sendServerError is sending 500 with message: ${message}`); // Log public response // Log detailed error information for debugging (internal only) // This provides developers with full context while keeping client responses generic if (error) { qerrors(error, 'sendServerError', { message, context }); // Structured error logging } // Send generic error response to client (never expose internal details) sendJsonResponse(res, 500, { error: message }); } /* * Module Export Strategy: * * Export all response utility functions to provide a complete toolkit for * standardized response handling across the application. Each function * serves a specific response pattern: * * - sendJsonResponse: General JSON responses * - sendValidationError: 400 validation errors * - sendAuthError: 401 authentication errors * - sendServerError: 500 internal server errors * * This covers the most common response patterns used throughout the codebase. */ module.exports = { sendJsonResponse, // export general JSON response sendValidationError, // export 400 error helper sendAuthError, // export 401 response helper sendServerError // export 500 response helper };