UNPKG

@athenna/http

Version:

The Athenna Http server. Built on top of fastify.

83 lines (82 loc) 2.8 kB
/** * @athenna/http * * (c) João Lenon <lenon@athenna.io> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ import { Is, Json, String, ExceptionHandler } from '@athenna/common'; import { Log } from '@athenna/logger'; export class HttpExceptionHandler extends ExceptionHandler { /** * Error codes that should be ignored from logging. */ get ignoreCodes() { return Config.get('http.logger.ignoreCodes', []); } /** * Error statuses that should be ignored from logging. */ get ignoreStatuses() { return Config.get('http.logger.ignoreStatuses', []); } /** * The exception handler of all request handlers. */ async handle({ error, response }) { let code = error.code; if (!Is.String(code) || Is.Undefined(code)) { code = error.name || 'E_INTERNAL_SERVER'; } const body = { statusCode: Json.copy(error.statusCode) || Json.copy(error.status) || 500, code: String.toSnakeCase(code).toUpperCase(), name: Json.copy(error.name), message: Json.copy(error.message), details: Json.copy(error.details), stack: Json.copy(error.stack) }; if (error.help) { body.help = Json.copy(error.help); } const isInternalServerError = Is.Error(error) && !Is.Exception(error); const isDebugMode = Config.is('app.debug', true); if (isInternalServerError && !isDebugMode) { body.code = 'E_INTERNAL_SERVER'; body.name = 'InternalServerException'; body.message = 'An internal server exception has occurred.'; delete body.details; } if (!isDebugMode) { delete body.stack; } await response.status(body.statusCode).send(body); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await super.handle({ error, response }); if (!this.canBeLogged(error)) { return; } if (!Is.Exception(error)) { error = error.toAthennaException(); } if (Config.is('http.logger.prettifyException', true)) { Log.channelOrVanilla('exception').error(await error.prettify()); return; } Log.channelOrVanilla('exception').error(error); } /** * Return a boolean indicating if the error can be logged or not. */ canBeLogged(error) { if (this.ignoreCodes.includes(error.code)) { return false; } if (this.ignoreStatuses.includes(error.status || error.statusCode)) { return false; } return true; } }