Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus as status } from '@nestjs/common'
- import { HttpArgumentsHost } from '@nestjs/common/interfaces'
- import { OutgoingMessage } from 'node:http'
- import { HttpAdapterHost } from '@nestjs/core'
- import { Request, Response } from 'express'
- import moment from 'moment-timezone'
- import { Logger } from '~/infrastructure/common/helpers/logger.helper'
- import { ELoggerType } from '~/domain/enums/common.enum'
- import { response } from '~/infrastructure/common/helpers/response.helper'
- import { IResponseInfo } from './domain/interfaces/common.interface'
- interface ErrorDetails {
- statCode: number
- errCode: string
- errMessage: string
- errors: any[]
- }
- @Catch()
- export class AppErrorException implements ExceptionFilter {
- private readonly defaultErrorCodes: Record<number, { errCode: string; errMessage?: string }> = {
- [status.INTERNAL_SERVER_ERROR]: { errCode: 'GENERAL_ERROR', errMessage: 'Application is busy, please try again later!' },
- [status.BAD_GATEWAY]: { errCode: 'SERVICE_ERROR', errMessage: 'Application is busy, please try again later!' },
- [status.SERVICE_UNAVAILABLE]: { errCode: 'SERVICE_UNAVAILABLE', errMessage: 'Application is not available, please try again later!' },
- [status.GATEWAY_TIMEOUT]: { errCode: 'SERVICE_TIMEOUT', errMessage: 'Application is timeout, please try again later!' },
- [status.CONFLICT]: { errCode: 'DUPLICATE_RESOURCE' },
- [status.UNPROCESSABLE_ENTITY]: { errCode: 'INVALID_REQUEST' },
- [status.PRECONDITION_FAILED]: { errCode: 'REQUEST_COULD_NOT_BE_PROCESSED' },
- [status.FORBIDDEN]: { errCode: 'ACCESS_DENIED' },
- [status.UNAUTHORIZED]: { errCode: 'UNAUTHORIZED_TOKEN' },
- [status.NOT_FOUND]: { errCode: 'UNKNOWN_RESOURCE' },
- }
- constructor(private readonly httpAdapterHost: HttpAdapterHost) {}
- private logError(exception: any): void {
- const name = 'ApplicationError'
- const type = ELoggerType.ERROR
- let message = ''
- if (exception instanceof HttpException) {
- message = `
- ====================================================
- ======== ${name} [HttpException] =========
- ====================================================
- name: ${exception.name}
- code: ${exception.getStatus()}
- message: ${exception.message}
- response: ${JSON.stringify(exception.getResponse())}
- stack: ${exception.stack}
- ====================================================
- ====================================================
- ====================================================
- `
- } else if (exception instanceof Error) {
- message = `
- ============================================
- ======== ${name} [Error] =========
- ============================================
- name: ${exception.name}
- message: ${exception.message}
- stack: ${exception.stack}
- ============================================
- ============================================
- ============================================
- `
- } else {
- message = `
- =============================================
- ======== ${name} [Common] =========
- =============================================
- name: ${exception.name}
- message: ${exception.message}
- response: ${JSON.stringify(exception)}
- stack: ${exception.stack}
- =============================================
- =============================================
- =============================================
- `
- }
- Logger.log(name, type, message, exception)
- }
- private getErrorDetails(exception: any): ErrorDetails {
- let statCode: number = status.INTERNAL_SERVER_ERROR
- let errMessage: string = ''
- let errors: any[] = []
- if (exception instanceof HttpException) {
- statCode = exception.getStatus()
- const response: any = exception.getResponse()
- if (typeof response === 'string') {
- errMessage = response
- } else if (response && typeof response === 'object') {
- if (response?.message) {
- errMessage = response?.message
- } else if (response?.error) {
- errMessage = response?.error
- }
- if (Array.isArray(response?.errors)) {
- errors = response?.errors
- }
- }
- } else if (exception instanceof Error) {
- errMessage = exception.message
- } else {
- if (exception.stat_code) {
- statCode = exception.stat_code
- }
- if (exception.error) {
- errMessage = exception.error
- } else if (exception.errors) {
- errors = exception.errors
- }
- }
- if (statCode === status.BAD_REQUEST) {
- statCode = status.UNPROCESSABLE_ENTITY
- } else if (statCode === status.FAILED_DEPENDENCY) {
- statCode = status.INTERNAL_SERVER_ERROR
- }
- const defaultError: Record<string, any> = this.defaultErrorCodes[statCode]
- const errCode: string = defaultError ? defaultError?.errCode : 'GENERAL_ERROR'
- if (defaultError && defaultError.errMessage && !errMessage) {
- errMessage = defaultError.errMessage
- }
- if (!errMessage && errors?.length === 0) {
- errMessage = 'An error occurred'
- }
- return { statCode, errCode, errMessage, errors }
- }
- private setHeader(req: Request, res: Response): void {
- const clientIpReq: string = req.header('X-Forwarded-For') || req.header('X-Real-IP') || req.header('X-Client-IP') || req.ip || req.socket.remoteAddress
- const serverDateTimeReq: string = moment(new Date()).format()
- res.set('X-Request-ID', req.header('X-Request-ID'))
- res.set('X-Client-IP', clientIpReq)
- res.set('X-Server-Time', serverDateTimeReq)
- }
- catch(exception: HttpException, host: ArgumentsHost): OutgoingMessage {
- const args: HttpArgumentsHost = host.switchToHttp()
- const req: Request = args.getRequest()
- const res: Response = args.getResponse()
- this.logError(exception)
- const { statCode, errCode, errMessage, errors } = this.getErrorDetails(exception)
- this.setHeader(req, res)
- const timestamp: string = moment(new Date()).format()
- const startTime: number = Number(req['startTime']) || Date.now()
- const serverInfo: IResponseInfo = {
- host: req.hostname,
- protocol: req.protocol,
- path: req.path,
- method: req.method,
- timestamp: timestamp,
- response_time: `${Date.now() - startTime} ms`,
- }
- const { httpAdapter }: HttpAdapterHost = this.httpAdapterHost
- if (errors.length > 0) {
- return httpAdapter.reply(res, response({ stat_code: statCode, err_code: errCode, errors, info: serverInfo }), statCode)
- } else {
- return httpAdapter.reply(res, response({ stat_code: statCode, err_code: errCode, error: errMessage, info: serverInfo }), statCode)
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement