qmemory
Version:
A comprehensive production-ready Node.js utility library with MongoDB document operations, user ownership enforcement, Express.js HTTP utilities, environment-aware logging, and in-memory storage. Features 96%+ test coverage with comprehensive error handli
194 lines (179 loc) • 9.2 kB
JavaScript
/**
* HTTP Utility Functions
* Common HTTP response helpers for Express applications
*
* This module centralizes HTTP response handling to ensure consistency
* across the application and reduce boilerplate code in route handlers.
* By standardizing response formats, we improve API consistency and
* make error handling more predictable for API consumers.
*
* Design philosophy:
* - Centralize common response patterns to avoid duplication
* - Provide consistent error message formats across the API
* - Simplify controller logic by abstracting HTTP response details
* - Enable easy modification of response formats in a single location
*
* Future extensions could include:
* - Additional status code helpers (sendBadRequest, sendUnauthorized, etc.)
* - Response formatting middleware
* - Logging integration for error tracking
*/
/**
* Validates Express response object for HTTP utility functions
*
* Centralized validation prevents runtime errors when HTTP utilities
* are called with invalid parameters. This helper ensures all HTTP
* functions receive valid Express response objects.
*
* @param {Object} res - Express response object to validate
* @throws {Error} When response object is invalid or missing required methods
*/
function validateResponseObject(res) { // validate object has expected methods for Express
if (!res || typeof res.status !== 'function' || typeof res.json !== 'function') { // confirm res has status() and json() functions
throw new Error('Invalid Express response object provided'); // throw explicit error to prevent silent failures
}
}
/**
* Sanitizes and formats message with fallback for HTTP responses
*
* Standardizes message handling across all HTTP utilities by trimming
* whitespace and providing fallback messages when input is invalid.
*
* @param {string} message - Input message to sanitize
* @param {string} fallback - Default message when input is invalid
* @returns {string} Sanitized message or fallback
*/
function sanitizeMessage(message, fallback) { // ensure clean error text for responses
console.log(`sanitizeMessage is running with ${message}, ${fallback}`); // trace call parameters for debugging
if (typeof message !== 'string') { // confirm message is string before trimming to avoid errors
console.log(`sanitizeMessage is returning ${fallback}`); // log default path when input invalid
return fallback; // use fallback when message type is incorrect
}
const trimmed = message.trim(); // remove surrounding whitespace from message input
const result = trimmed || fallback; // choose fallback when trimmed string is empty
console.log(`sanitizeMessage is returning ${result}`); // log sanitized or fallback message
return result; // return final sanitized message
}
/**
* Generates ISO timestamp for HTTP response consistency
*
* Centralizes timestamp generation to ensure consistent format
* across all HTTP responses and enable future format changes.
*
* @returns {string} ISO 8601 formatted timestamp
*/
function getTimestamp() { // create consistent timestamp for logs and responses
return new Date().toISOString(); // ISO format chosen for cross-system compatibility
}
/**
* Sends a 404 Not Found response with a custom message
*
* This utility standardizes 404 responses across the application,
* ensuring consistent error formatting and reducing boilerplate in
* route handlers. It follows REST API conventions by providing
* both an appropriate status code and descriptive error message.
*
* Design rationale:
* - Uses 404 status code which is the standard HTTP response for "resource not found"
* - Provides JSON response format for consistency with API expectations
* - Accepts custom message to allow context-specific error descriptions
* - Encapsulates response logic to keep controllers focused on business logic
*
* Usage pattern: This function is typically called when database queries
* return null/undefined, indicating the requested resource doesn't exist
* or the user doesn't have permission to access it.
*
* Alternative approaches considered:
* - Throwing errors instead of direct response: would require additional error handling middleware
* - Including error codes: adds complexity that may not be needed for simple cases
* - Template-based messages: more complex but could provide better internationalization
*
* @param {Object} res - Express response object used to send the HTTP response
* @param {string} message - Custom error message describing what was not found
*/
function sendNotFound(res, message) {
// Input validation for production safety - ensure valid Express response object
// This prevents runtime errors when called with invalid parameters
validateResponseObject(res);
// Send standardized 404 Not Found response with custom message
// 404 is the correct HTTP status for "resource not found" scenarios
// This centralizes error response formatting and ensures consistency across all endpoints
return res.status(404).json({
message: sanitizeMessage(message, 'Resource not found'), // message gives client context while preventing injection via sanitize
timestamp: getTimestamp() // timestamp aids log correlation for debugging
}); // Return response object for method chaining in Express route handlers
}
/**
* Sends a 409 Conflict response with a custom message
*
* Standardizes conflict responses for duplicate resource creation attempts.
* Used when uniqueness constraints are violated or resource conflicts occur.
*
* @param {Object} res - Express response object used to send the HTTP response
* @param {string} message - Custom error message describing the conflict
*/
function sendConflict(res, message) {
// Input validation for production safety - ensure valid response object
validateResponseObject(res);
return res.status(409).json({
message: sanitizeMessage(message, 'Resource conflict'), // message clarifies duplicate or conflicting request
timestamp: getTimestamp() // timestamp documents when conflict occurred
}); // Follows same pattern as sendNotFound - now with validation and timestamp
}
/**
* Sends a 500 Internal Server Error response with a custom message
*
* Standardizes internal server error responses for unexpected failures.
* Used when server-side problems occur that aren't client-related.
*
* @param {Object} res - Express response object used to send the HTTP response
* @param {string} message - Custom error message describing the internal error
*/
function sendInternalServerError(res, message) {
// Input validation for production safety - ensure valid Express response object
// Critical for preventing crashes when called with malformed parameters
validateResponseObject(res);
// Log errors for monitoring and debugging - always log 500s for investigation
// Stack trace included to help identify source of unexpected errors
console.error(`[ERROR] Internal server error: ${message}`, {
timestamp: getTimestamp(),
stack: new Error().stack // Stack trace helps pinpoint error source in production
});
return res.status(500).json({
message: sanitizeMessage(message, 'Internal server error'), // message keeps user informed without leaking server internals
timestamp: getTimestamp() // timestamp records when the error occurred for log lookup
}); // 500 status indicates server-side failure requiring investigation
}
/**
* Sends a 503 Service Unavailable response with a custom message
*
* Standardizes service unavailable responses for dependency failures.
* Used when external services (like databases) are temporarily unavailable.
*
* @param {Object} res - Express response object used to send the HTTP response
* @param {string} message - Custom error message describing the unavailable service
*/
function sendServiceUnavailable(res, message) {
// Input validation for production safety - ensure valid Express response object
// Essential for preventing failures when dependencies are down
validateResponseObject(res);
// Log service unavailable events for monitoring and alerting
// WARN level appropriate for dependency issues that require attention
console.warn(`[WARN] Service unavailable: ${message}`, {
timestamp: getTimestamp()
});
return res.status(503).json({
message: sanitizeMessage(message, 'Service temporarily unavailable'), // message informs client of temporary outage without internals
timestamp: getTimestamp(), // timestamp helps track service downtime periods
retryAfter: '300' // Retry-After header value indicates when the client may retry
}); // 503 status indicates temporary service disruption, not permanent failure
}
// Export using object shorthand for clean module interface
// This pattern allows for easy extension with additional HTTP utilities
// while maintaining a simple import structure for consumers
module.exports = {
sendNotFound, // helper for 404 responses
sendConflict, // helper for 409 responses
sendInternalServerError, // helper for 500 responses
sendServiceUnavailable // helper for 503 responses
};