Разработка REST API для веб-приложения
REST (Representational State Transfer) — архитектурный стиль API на основе HTTP. Стандарт де-факто для веб-приложений, основанный на ресурсах, HTTP-методах и статус-кодах. Хорошо спроектированный REST API — предсказуем, кэшируем и масштабируется горизонтально.
Ключевые принципы
Ресурсоориентированность: URL идентифицирует ресурс, HTTP-метод определяет действие:
GET /api/v1/articles — список статей
POST /api/v1/articles — создать статью
GET /api/v1/articles/42 — статья с id=42
PUT /api/v1/articles/42 — полное обновление
PATCH /api/v1/articles/42 — частичное обновление
DELETE /api/v1/articles/42 — удалить
GET /api/v1/articles/42/comments — комментарии статьи
Stateless: каждый запрос содержит всю информацию для его обработки. Никакого серверного состояния сессии между запросами.
Единообразие ответов:
// Успех
{
"data": { "id": 42, "title": "..." },
"meta": { "total": 1 }
}
// Список
{
"data": [...],
"meta": { "total": 150, "page": 1, "per_page": 20 }
}
// Ошибка
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Поле title обязательно",
"details": [{ "field": "title", "message": "required" }]
}
}
HTTP-коды статуса
Правильное использование кодов — важная часть контракта:
| Код | Ситуация |
|---|---|
| 200 OK | Успешный GET, PUT, PATCH |
| 201 Created | Успешный POST, ресурс создан |
| 204 No Content | Успешный DELETE |
| 400 Bad Request | Ошибка валидации |
| 401 Unauthorized | Нет или неверный токен |
| 403 Forbidden | Нет прав (токен валиден) |
| 404 Not Found | Ресурс не найден |
| 409 Conflict | Конфликт (дубликат email) |
| 422 Unprocessable Entity | Семантическая ошибка |
| 429 Too Many Requests | Rate limit превышен |
| 500 Internal Server Error | Неожиданная ошибка сервера |
Пагинация
Три подхода:
Offset-based (page + per_page):
GET /api/articles?page=2&per_page=20
Просто, но медленнее на больших объёмах из-за OFFSET N в SQL.
Cursor-based (after + limit):
GET /api/articles?after=eyJpZCI6NDJ9&limit=20
Cursor — зашифрованное значение последней записи. Быстро на любом объёме, но нельзя «прыгнуть» на страницу N.
Keyset (after_id + limit): упрощённый cursor через first ID:
GET /api/articles?after_id=42&limit=20
Фильтрация и сортировка
GET /api/articles?status=published&author_id=5&created_after=2024-01-01
GET /api/articles?sort=created_at&order=desc&fields=id,title,slug
Включение связанных данных (include):
GET /api/articles/42?include=author,tags,comments_count
Версионирование
URL-версионирование — наиболее явный способ:
/api/v1/articles
/api/v2/articles — breaking change
Альтернатива — Accept header: Accept: application/vnd.app.v2+json.
Пример реализации (Laravel)
// routes/api.php
Route::prefix('v1')->middleware('auth:sanctum')->group(function () {
Route::apiResource('articles', ArticleController::class);
Route::get('articles/{article}/comments', [CommentController::class, 'index']);
});
// ArticleController
public function index(IndexArticleRequest $request)
{
$articles = Article::query()
->when($request->status, fn($q, $v) => $q->where('status', $v))
->with($request->include ?? [])
->paginate($request->per_page ?? 20);
return ArticleResource::collection($articles);
}
Сроки
REST API для CRUD-приложения (10–20 эндпоинтов, авторизация, валидация, документация): 1–2 недели.







