Обработка ошибок
Ошибки случаются: статья не найдена, у пользователя нет прав, база недоступна. AdonisJS ловит все исключения, которые вылетели из маршрутов и контроллеров, в одном месте — глобальном обработчике. Он решает, что показать посетителю и что записать в журнал.
Обработчик
Файл app/exceptions/handler.ts уже есть в проекте:
// app/exceptions/handler.ts
import app from '@adonisjs/core/services/app'
import { HttpContext, ExceptionHandler } from '@adonisjs/core/http'
import type { StatusPageRange, StatusPageRenderer } from '@adonisjs/core/types/http'
export default class HttpExceptionHandler extends ExceptionHandler {
protected debug = !app.inProduction
protected renderStatusPages = app.inProduction
protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
'404': (error, { view }) => view.render('pages/errors/not_found', { error }),
'500..599': (error, { view }) => view.render('pages/errors/server_error', { error }),
}
async handle(error: unknown, ctx: HttpContext) {
return super.handle(error, ctx)
}
async report(error: unknown, ctx: HttpContext) {
return super.report(error, ctx)
}
}| Свойство или метод | Что делает |
|---|---|
debug | В разработке показывает подробную страницу с ошибкой и стеком вызовов |
renderStatusPages | На сервере включает красивые страницы ошибок |
statusPages | Какой шаблон показать для какого статуса |
handle | Формирует ответ посетителю |
report | Записывает ошибку в журнал |
Страница 404
{{-- resources/views/pages/errors/not_found.edge --}}
@layout({ title: 'Страница не найдена' })
<h1>Такой страницы нет</h1>
<p><a href="{{ route('posts.index') }}">Вернуться к статьям</a></p>
@endШаблон показывается для любого ответа 404, например когда Post.findOrFail не нашёл статью. В режиме разработки вместо него вы увидите отладочную страницу; чтобы проверить свою, временно поставьте renderStatusPages = true.
Своё исключение
node ace make:exception PostLocked// app/exceptions/post_locked_exception.ts
import { Exception } from '@adonisjs/core/exceptions'
export default class PostLockedException extends Exception {
static status = 423
static code = 'E_POST_LOCKED'
static message = 'Статья закрыта для комментариев'
}// app/controllers/comments_controller.ts
import PostLockedException from '#exceptions/post_locked_exception'
if (post.isLocked) {
throw new PostLockedException()
}Обработчик вернёт статус 423 и текст сообщения: для JSON-клиента — в JSON, для браузера — страницей.
Свой ответ для исключения
Исключение может само решить, как отвечать, — для этого в нём объявляют метод handle:
// app/exceptions/post_locked_exception.ts
async handle(error: this, ctx: HttpContext) {
ctx.session.flash('error', error.message)
return ctx.response.redirect().back()
}Тогда посетитель вернётся на страницу статьи и увидит flash-сообщение. HttpContext импортируйте из @adonisjs/core/http.
Частая ошибка
На сервере забывают выставить NODE_ENV=production. Тогда app.inProduction ложно, debug включён, и при любой ошибке посетитель видит стек вызовов, пути к файлам и куски кода. Проверяйте NODE_ENV в .env рабочего сервера.