Урок 09

Обработка ошибок API

Стандартные коды

  • 200 — OK
  • 201 — Created
  • 204 — No Content
  • 400 — Bad Request
  • 401 — Unauthorized (не авторизован)
  • 403 — Forbidden (нет прав)
  • 404 — Not Found
  • 422 — Unprocessable Entity (ошибки валидации)
  • 429 — Too Many Requests
  • 500 — Internal Server Error

Формат ошибок Laravel

{
    "message": "No query results for model [App\\Models\\Post] 5"
}

Валидация:

{
    "message": "The title field is required.",
    "errors": {
        "title": ["The title field is required."]
    }
}

Кастомные ответы

return response()->json(['error' => 'Not found'], 404);
return response()->json(['message' => 'Создано'], 201);

Исключения

abort(404, 'Пост не найден');
abort(403, 'Нет доступа');
abort_if(!$post->published, 404);
abort_unless($request->user()->isAdmin(), 403);

Кастомизация в bootstrap/app.php

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (ModelNotFoundException $e, Request $request) {
        if ($request->is('api/*')) {
            return response()->json([
                'message' => 'Ресурс не найден',
            ], 404);
        }
    });
})

Обработка всех исключений

$exceptions->render(function (Throwable $e, Request $request) {
    if ($request->is('api/*')) {
        return response()->json([
            'message' => $e->getMessage(),
            'code' => $e->getCode(),
        ], 500);
    }
});

Только в dev — на проде не показывай сообщения исключений.

HTTP-исключения

throw new \Illuminate\Http\Exceptions\HttpResponseException(
    response()->json(['error' => 'Custom'], 400)
);

Логирование

Log::error('API error', [
    'endpoint' => $request->path(),
    'user_id' => $request->user()?->id,
    'message' => $e->getMessage(),
]);

Rate limit

При превышении возвращается 429 с заголовком Retry-After:

{
    "message": "Too Many Attempts."
}