Tratamento de exceções
Exceções levantadas durante uma solicitação HTTP são tratadas pelo HttpExceptionHandler
definido dentro do arquivo ./app/exceptions/handler.ts
. Dentro deste arquivo, você pode decidir como converter exceções em respostas e registrá-las usando o logger ou relatá-las a um provedor de registro externo.
O HttpExceptionHandler
estende a classe ExceptionHandler, que faz todo o trabalho pesado de tratamento de erros e fornece APIs de alto nível para ajustar o comportamento de relatórios e renderização.
import app from '@adonisjs/core/services/app'
import { HttpContext, ExceptionHandler } from '@adonisjs/core/http'
export default class HttpExceptionHandler extends ExceptionHandler {
protected debug = !app.inProduction
protected renderStatusPages = app.inProduction
async handle(error: unknown, ctx: HttpContext) {
return super.handle(error, ctx)
}
async report(error: unknown, ctx: HttpContext) {
return super.report(error, ctx)
}
}
Atribuindo manipulador de erros ao servidor
O manipulador de erros é registrado com o servidor HTTP AdonisJS dentro do arquivo start/kernel.ts
. Importamos preguiçosamente o manipulador HTTP usando o alias #exceptions
definido no arquivo package.json
.
server.errorHandler(() => import('#exceptions/handler'))
Lidando com exceções
As exceções são tratadas pelo método handle
na classe do manipulador de exceções. Por padrão, as seguintes etapas são executadas durante o tratamento de um erro.
- error.handle e retorna sua resposta.
- Verifique se uma página de status está definida para o código
error.status
. Se sim, renderize a página de status. - Caso contrário, renderize a exceção usando renderizadores de negociação de conteúdo.
Se você quiser lidar com uma exceção específica de forma diferente, pode fazer isso dentro do método handle
. Certifique-se de usar o método ctx.response.send
para enviar uma resposta, pois o valor de retorno do método handle
é descartado.
import { errors } from '@vinejs/vine'
export default class HttpExceptionHandler extends ExceptionHandler {
async handle(error: unknown, ctx: HttpContext) {
if (error instanceof errors.E_VALIDATION_ERROR) {
ctx.response.status(422).send(error.messages)
return
}
return super.handle(error, ctx)
}
}
Páginas de status
Páginas de status são uma coleção de modelos que você deseja renderizar para um determinado ou um intervalo de códigos de status.
O intervalo de códigos de status pode ser definido como uma expressão de string. Dois pontos separam os códigos de status inicial e final (..
).
Se você estiver criando um servidor JSON, pode não precisar de páginas de status.
import { StatusPageRange, StatusPageRenderer } from '@adonisjs/http-server/types'
export default class HttpExceptionHandler extends ExceptionHandler {
protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
'404': (_, { view }) => view.render('errors/not-found'),
'500..599': (_, { view }) => view.render('errors/server-error')
}
}
Modo de depuração
Os renderizadores de negociação de conteúdo manipulam exceções que não são automanipuladas e não convertidas em uma página de status.
Os renderizadores de negociação de conteúdo têm suporte para o modo de depuração. Eles podem analisar e imprimir erros no modo de depuração usando o pacote npm Youch.
Você pode alternar o modo de depuração usando a propriedade debug
na classe do manipulador de exceções. No entanto, é recomendável desativar o modo de depuração na produção, pois ele expõe informações confidenciais sobre seu aplicativo.
export default class HttpExceptionHandler extends ExceptionHandler {
protected debug = !app.inProduction
}
Relatando exceções
O método report
na classe do manipulador de exceções manipula o relatório de exceções.
O método recebe o erro como o primeiro argumento e o contexto HTTP como o segundo argumento. Você não deve escrever uma resposta do método report
e usar o contexto apenas para ler as informações da solicitação.
Registrando exceções
Todas as exceções são relatadas usando o logger por padrão.
- Exceções com códigos de status no intervalo
400..499
são registradas no nívelwarning
. - Exceções com o código de status
>=500
são registradas no nívelerror
. - Todas as outras exceções são registradas no nível
info
.
Você pode adicionar propriedades personalizadas às mensagens de log retornando um objeto do método context
.
export default class HttpExceptionHandler extends ExceptionHandler {
protected context(ctx: HttpContext) {
return {
requestId: ctx.requestId,
userId: ctx.auth.user?.id,
ip: ctx.request.ip(),
}
}
}
Ignorando códigos de status
Você pode ignorar exceções de serem relatadas definindo uma matriz de códigos de status por meio da propriedade ignoreStatuses
.
export default class HttpExceptionHandler extends ExceptionHandler {
protected ignoreStatuses = [
401,
400,
422,
403,
]
}
Ignorando erros
Você também pode ignorar exceções definindo uma matriz de códigos de erro ou classes de erro para ignorar.
import { errors } from '@adonisjs/core'
import { errors as sessionErrors } from '@adonisjs/session'
export default class HttpExceptionHandler extends ExceptionHandler {
protected ignoreCodes = [
'E_ROUTE_NOT_FOUND',
'E_INVALID_SESSION'
]
}
Uma matriz de classes de exceção pode ser ignorada usando a propriedade ignoreExceptions
.
import { errors } from '@adonisjs/core'
import { errors as sessionErrors } from '@adonisjs/session'
export default class HttpExceptionHandler extends ExceptionHandler {
protected ignoreExceptions = [
errors.E_ROUTE_NOT_FOUND,
sessionErrors.E_INVALID_SESSION,
]
}
Método shouldReport personalizado
A lógica para ignorar códigos de status ou exceções é escrita dentro do método shouldReport
. Se necessário, você pode substituir esse método e definir sua lógica personalizada para ignorar exceções.
import { HttpError } from '@adonisjs/core/types/http'
export default class HttpExceptionHandler extends ExceptionHandler {
protected shouldReport(error: HttpError) {
// retornar um booleano
}
}
Exceções personalizadas
Você pode criar uma classe de exceção usando o comando ace make:exception
. Uma exceção estende a classe Exception
do pacote @adonisjs/core
.
Veja também: Comando Make exception
node ace make:exception UnAuthorized
import { Exception } from '@adonisjs/core/exceptions'
export default class UnAuthorizedException extends Exception {}
Você pode levantar a exceção criando uma nova instância dela. Ao levantar a exceção, você pode atribuir um código de erro e um código de status personalizados à exceção.
import UnAuthorizedException from '#exceptions/unauthorized_exception'
throw new UnAuthorizedException('You are not authorized', {
status: 403,
code: 'E_UNAUTHORIZED'
})
Os códigos de erro e status também podem ser definidos como propriedades estáticas na classe de exceção. Os valores estáticos serão usados se nenhum valor personalizado for definido ao lançar a exceção.
import { Exception } from '@adonisjs/core/exceptions'
export default class UnAuthorizedException extends Exception {
static status = 403
static code = 'E_UNAUTHORIZED'
}
Definindo o método handle
Para automanipular a exceção, você pode definir o método handle
na classe de exceção. Este método deve converter um erro em uma resposta HTTP usando o método ctx.response.send
.
O método error.handle
recebe uma instância do erro como o primeiro argumento e o contexto HTTP como o segundo argumento.
import { Exception } from '@adonisjs/core/exceptions'
import { HttpContext } from '@adonisjs/core/http'
export default class UnAuthorizedException extends Exception {
async handle(error: this, ctx: HttpContext) {
ctx.response.status(error.status).send(error.message)
}
}
Defina o método report
Você pode implementar o método report
na classe de exceção para automanipular o relatório de exceção. O método report recebe uma instância do erro como o primeiro argumento e o contexto HTTP como o segundo argumento.
import { Exception } from '@adonisjs/core/exceptions'
import { HttpContext } from '@adonisjs/core/http'
export default class UnAuthorizedException extends Exception {
async report(error: this, ctx: HttpContext) {
ctx.logger.error({ err: error }, error.message)
}
}
Restringindo o tipo de erro
O núcleo do framework e outros pacotes oficiais exportam as exceções geradas por eles. Você pode verificar se um erro é uma instância de uma exceção específica usando a verificação instanceof
. Por exemplo:
import { errors } from '@adonisjs/core'
try {
router.builder().make('articles.index')
} catch (error: unknown) {
if (error instanceof errors.E_CANNOT_LOOKUP_ROUTE) {
// manipular erro
}
}
Erros conhecidos
- Guia de referência de exceções para visualizar a lista de erros conhecidos.