CRUD и HTTP-методы

CRUD (Create, Read, Update, Delete) — четыре базовые операции над данными, которые в REST API реализуются соответствующими HTTP-методами.

Зачем нужно

Понимание маппинга CRUD на HTTP-методы — фундамент проектирования REST API. Правильный выбор метода делает API предсказуемым, позволяет браузерам и прокси кэшировать ответы, а клиентам — строить запросы по очевидным соглашениям.

Где используется

  • Проектирование REST-эндпоинтов бэкенда
  • Реализация CRUD в Express, Fastify, NestJS
  • Написание клиентских fetch-запросов с правильными методами
  • Документирование API в OpenAPI/Swagger

CRUD ↔ HTTP маппинг

CRUD HTTP метод Идемпотентный Безопасный Пример URL
Create POST нет нет POST /api/users
Read GET да да GET /api/users/42
Update (полное) PUT да нет PUT /api/users/42
Update (частичное) PATCH нет* нет PATCH /api/users/42
Delete DELETE да нет DELETE /api/users/42

* PATCH может быть идемпотентным — зависит от реализации.

Примеры запросов

# CREATE — создать пользователя
POST /api/users HTTP/1.1
Content-Type: application/json

{"name": "Антон", "email": "anton@example.com"}

# → 201 Created
# Location: /api/users/42
# READ — получить список
GET /api/users?page=1&limit=20 HTTP/1.1

# → 200 OK
# [{"id": 1, "name": "..."}, ...]

# READ — один объект
GET /api/users/42 HTTP/1.1

# → 200 OK  или  404 Not Found
# UPDATE (полное) — заменить весь объект
PUT /api/users/42 HTTP/1.1
Content-Type: application/json

{"name": "Антон", "email": "new@example.com", "role": "admin"}

# → 200 OK

# UPDATE (частичное) — изменить только email
PATCH /api/users/42 HTTP/1.1
Content-Type: application/json

{"email": "new@example.com"}

# → 200 OK
# DELETE
DELETE /api/users/42 HTTP/1.1

# → 204 No Content

Реализация на fetch

const BASE = 'https://api.example.com';

// Create
async function createUser(data) {
  const res = await fetch(`${BASE}/users`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });
  if (!res.ok) throw new Error(res.statusText);
  return res.json(); // 201
}

// Read
async function getUser(id) {
  const res = await fetch(`${BASE}/users/${id}`);
  if (res.status === 404) return null;
  return res.json();
}

// Update (PATCH)
async function patchUser(id, changes) {
  const res = await fetch(`${BASE}/users/${id}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(changes),
  });
  return res.json();
}

// Delete
async function deleteUser(id) {
  const res = await fetch(`${BASE}/users/${id}`, { method: 'DELETE' });
  return res.status === 204;
}

Частые ошибки

  • Использование POST для всех операций вместо GET/PUT/DELETE
  • PUT без передачи полного объекта — забытые поля становятся null
  • Возврат 200 при удалении вместо 204 No Content
  • Путаница PUT и PATCH: PUT заменяет объект целиком, PATCH — частично
  • GET-запросы с телом (body) — нарушает спецификацию и ломает кэши

Связанные темы

Ресурсы