UNPKG

@elsikora/nestjs-crud-automator

Version:

A library for automating the creation of CRUD operations in NestJS.

101 lines (98 loc) 6.41 kB
'use strict'; var tslib_es6 = require('../external/tslib/tslib.es6.js'); var node_crypto = require('node:crypto'); var common = require('@nestjs/common'); var throttler = require('@nestjs/throttler'); var formatUnknownForLog_utility = require('../utility/format-unknown-for-log.utility.js'); var logger_utility = require('../utility/logger.utility.js'); var operators = require('rxjs/operators'); const interceptorLogger = logger_utility.LoggerUtility.getLogger("CorrelationIDResponseBodyInterceptor"); /** * Global interceptor that adds correlation IDs and timestamps to all error responses. * @see {@link https://elsikora.com/docs/nestjs-crud-automator/api-reference/interceptors | API Reference - Interceptors} * @see {@link https://elsikora.com/docs/nestjs-crud-automator/guides/error-handling | Guides - Error Handling} */ exports.CorrelationIDResponseBodyInterceptor = class CorrelationIDResponseBodyInterceptor { intercept(context, next) { const request = context.switchToHttp().getRequest(); const reply = context.switchToHttp().getResponse(); const rawCorrelationId = request.headers["x-correlation-id"]; const headerCorrelationId = Array.isArray(rawCorrelationId) ? rawCorrelationId.find((value) => value.trim().length > 0) : rawCorrelationId; const normalizedCorrelationId = typeof headerCorrelationId === "string" ? headerCorrelationId.trim() : undefined; const correlationId = normalizedCorrelationId && normalizedCorrelationId.length > 0 ? normalizedCorrelationId : node_crypto.randomUUID(); const requestMethod = request.method ?? "UNKNOWN_METHOD"; const requestUrl = request.url ?? "UNKNOWN_URL"; // Persist the resolved correlation ID for downstream loggers/middlewares request.headers["x-correlation-id"] = correlationId; request.correlationID = correlationId; reply.header("x-correlation-id", correlationId); return next.handle().pipe(operators.catchError((error) => { if (error instanceof throttler.ThrottlerException) { const errorResponse = error.getResponse(); interceptorLogger.warn(`HTTP ${common.HttpStatus.TOO_MANY_REQUESTS} ${requestMethod} ${requestUrl} correlationID=${correlationId}`); let customErrorResponse = { statusCode: common.HttpStatus.TOO_MANY_REQUESTS }; if (typeof errorResponse === "object" && errorResponse != null) { customErrorResponse = { ...errorResponse }; } else { customErrorResponse.message = errorResponse; } customErrorResponse.error = "Too Many Requests"; customErrorResponse.timestamp = Date.now(); customErrorResponse.correlationID = correlationId; throw new common.HttpException(customErrorResponse, error.getStatus()); } else if (error instanceof common.HttpException) { const errorResponse = error.getResponse(); const status = error.getStatus(); if (status >= common.HttpStatus.INTERNAL_SERVER_ERROR) { const errorStack = error instanceof Error ? error.stack : undefined; interceptorLogger.error(`HTTP ${status} ${requestMethod} ${requestUrl} correlationID=${correlationId}`, errorStack); const cause = error.cause; if (cause instanceof Error) { interceptorLogger.error(`Cause: ${cause.name}: ${cause.message} correlationID=${correlationId}`, cause.stack); } else if (cause != null) { interceptorLogger.error(`Cause: ${formatUnknownForLog_utility.FormatUnknownForLog(cause)} correlationID=${correlationId}`); } } let customErrorResponse = {}; if (typeof errorResponse === "object" && errorResponse != null) { customErrorResponse = { ...errorResponse }; } else { customErrorResponse.message = errorResponse; } customErrorResponse.correlationID = correlationId; customErrorResponse.timestamp = Date.now(); throw new common.HttpException(customErrorResponse, status); } else { if (error instanceof Error) { interceptorLogger.error(`HTTP ${common.HttpStatus.INTERNAL_SERVER_ERROR} ${requestMethod} ${requestUrl} correlationID=${correlationId} (non-HttpException)`, error.stack); if (error.cause instanceof Error) { interceptorLogger.error(`Cause: ${error.cause.name}: ${error.cause.message} correlationID=${correlationId}`, error.cause.stack); } else if (error.cause != null) { interceptorLogger.error(`Cause: ${formatUnknownForLog_utility.FormatUnknownForLog(error.cause)} correlationID=${correlationId}`); } } else { interceptorLogger.error(`HTTP ${common.HttpStatus.INTERNAL_SERVER_ERROR} ${requestMethod} ${requestUrl} correlationID=${correlationId} (non-Error thrown): ${formatUnknownForLog_utility.FormatUnknownForLog(error)}`); } if (!(error instanceof Error)) { error = new common.InternalServerErrorException("Unknown error"); } const internalError = error; const errorResponse = "Internal server error"; const customErrorResponse = { correlationID: correlationId, error: "Internal server error", message: errorResponse, statusCode: common.HttpStatus.INTERNAL_SERVER_ERROR, timestamp: Date.now() }; const status = "getStatus" in internalError && typeof internalError.getStatus === "function" ? internalError.getStatus() : common.HttpStatus.INTERNAL_SERVER_ERROR; throw new common.HttpException(customErrorResponse, status); } })); } }; exports.CorrelationIDResponseBodyInterceptor = tslib_es6.__decorate([ common.Injectable() ], exports.CorrelationIDResponseBodyInterceptor); //# sourceMappingURL=correlation-id-response-body.interceptor.js.map