Search by

gian-tiaga / spiral-api-errors

gian_tiaga

API error handling package for typed Spiral HTTP layers

Package info

github.com/falur/spiral-api-errors

pkg:composer/gian-tiaga/spiral-api-errors

Statistics

Installs: 16

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-09-14 14:38 UTC

This package is auto-updated.

Last update: 2026-09-14 14:48:13 UTC


README

gian-tiaga/spiral-api-errors приводит ошибки HTTP API к одному JSON-формату в Spiral-приложениях.

Пакет обрабатывает:

  • ненайденный HTTP-маршрут;
  • ошибки Spiral Filter;
  • ожидаемые доменные ошибки с HTTP-кодом 4xx;
  • непредвиденные ошибки как безопасный ответ 500.

Установка

composer require gian-tiaga/spiral-api-errors:^0.1.0

Пакет использует response-классы из gian-tiaga/spiral-openapi; Composer установит эту зависимость автоматически.

Bootloader

Подключите ApiErrorBootloader до bootloader-а маршрутов, чтобы Spiral Filter получил JSON renderer ошибок:

use GianTiaga\SpiralApiErrors\Bootloader\ApiErrorBootloader;

protected const LOAD = [
    ApiErrorBootloader::class,
    RoutesBootloader::class,
];

Bootloader подключает каталог переводов и регистрирует:

  • ApiValidationErrorsRenderer;
  • ApiExceptionInterceptor;
  • RouteNotFoundMiddleware.

Middleware

RouteNotFoundMiddleware нужно поставить сразу после стандартного обработчика ошибок Spiral:

use GianTiaga\SpiralApiErrors\Middleware\RouteNotFoundMiddleware;
use Spiral\Http\Middleware\ErrorHandlerMiddleware;

protected function globalMiddleware(): array
{
    return [
        ErrorHandlerMiddleware::class,
        RouteNotFoundMiddleware::class,
    ];
}

Ответ 404:

{
  "message": "Маршрут не найден.",
  "code": 404
}

Interceptor

ApiExceptionInterceptor ставится после HttpResponseInterceptor в списке interceptors. Тогда response DTO сначала превращаются в HTTP-ответы, а доменные исключения получают единый JSON-формат.

use GianTiaga\SpiralApiErrors\Interceptor\ApiExceptionInterceptor;
use GianTiaga\SpiralOpenApi\Response\Interceptor\HttpResponseInterceptor;

protected const array INTERCEPTORS = [
    HttpResponseInterceptor::class,
    ApiExceptionInterceptor::class,
];

Доменная ошибка с кодом 4xx:

{
  "message": "Ресурс не найден",
  "code": 404
}

Непредвиденная ошибка:

{
  "message": "Внутренняя ошибка сервера",
  "code": 500
}

Внутреннее сообщение непредвиденного исключения не отдаётся наружу, но пишется в лог.

Ошибки Filter

ApiValidationErrorsRenderer возвращает 422:

{
  "message": "Ошибка валидации",
  "code": 422,
  "errors": [
    {
      "field": "email",
      "message": "Некорректный email"
    }
  ]
}

Сообщение верхнего уровня переводится пакетом. Сообщения отдельных полей уже принадлежат приложению, поэтому пакет их не переводит.

Locale

Пакет использует текущий locale Spiral\Translator\TranslatorInterface.

Ключи переводов:

  • gian_tiaga.spiral_api_errors.route_not_found;
  • gian_tiaga.spiral_api_errors.validation_error;
  • gian_tiaga.spiral_api_errors.internal_server_error.

Поддерживаются ru и en.

Граница ответственности

Пакет не содержит доменные исключения приложения и не зависит от его namespace. Для ожидаемых бизнес-ошибок приложение само задаёт сообщение и HTTP-код 4xx; пакет только оборачивает их в общий response.

Локальная разработка

Чтобы править пакет рядом с приложением, подключите его каталог path repository — путь считается от корня приложения:

{
  "repositories": [
    {
      "type": "path",
      "url": "../spiral-api-errors",
      "options": {
        "symlink": true
      }
    }
  ]
}

Проверки пакета:

composer install
composer test
composer phpstan