REST и GraphQL
REST API — основные принципы
REST — архитектурный стиль, сформулированный Роем Филдингом в 2000 году для построения API. Не протокол и не стандарт.
6 принципов:
1. Client-Server — клиент и сервер разделены, не знают о внутреннем устройстве друг друга. Можно менять их независимо.
2. Stateless — каждый запрос содержит всю информацию для его обработки. Сервер не хранит сессию — если нужна авторизация, токен передаётся в каждом запросе.
3. Cacheable — ответы явно указывают, можно ли их кэшировать. GET кэшируется по умолчанию, POST/PUT/DELETE — только при явных заголовках.
4. Uniform Interface — ресурсы идентифицируются через URI, используются стандартные HTTP-методы, данные передаются в стандартном формате (JSON/XML).
5. Layered System — между клиентом и сервером могут быть промежуточные слои (прокси, балансировщики, CDN). Клиент не знает, с кем общается напрямую.
6. Code on Demand (опционально) — сервер может передавать клиенту исполняемый код (например, JS). Единственный необязательный принцип.
На практике большинство API реализуют первые 4 принципа и считаются «достаточно RESTful».
GET /users — список пользователей
GET /users/1 — конкретный пользователь
POST /users — создать пользователя
PUT /users/1 — полностью обновить (все поля)
PATCH /users/1 — частично обновить (некоторые поля)
DELETE /users/1 — удалить
HEAD /users/1 — то же что GET, но без тела ответа; только заголовки
(проверить существование, размер, дату изменения,
валидность кэша)
OPTIONS /users — вернуть список поддерживаемых методов для ресурса
(браузер автоматически отправляет перед cross-origin
запросом — preflight)
TRACE /users — диагностика: сервер возвращает запрос обратно как есть
(используется для отладки цепочки прокси; в проде обычно
отключён)
CONNECT — — установить TCP-туннель через прокси (используется для HTTPS через HTTP-прокси)
(не применяется в REST API напрямую)
Основные методы REST API
| Метод | Идемпотентен? | Тело запроса | Кэшируется? | Описание |
|---|---|---|---|---|
GET | ✅ | ❌ | ✅ | Получить данные |
POST | ❌ | ✅ | ⚠️ Только явно | Создать ресурс |
PUT | ✅ | ✅ | ❌ | Полная замена |
PATCH | ⚠️ Зависит | ✅ | ❌ | Частичное обновление |
DELETE | ✅ | ❌ | ❌ | Удалить |
HEAD | ✅ | ❌ | ✅ | Как GET, но только заголовки |
OPTIONS | ✅ | ❌ | ❌ | Список поддерживаемых методов |
TRACE | ✅ | ❌ | ❌ | Диагностика, возвращает запрос обратно |
CONNECT | ❌ | ❌ | ❌ | TCP-туннель через прокси |
Идемпотентен — повторный вызов с теми же параметрами даёт тот же результат. DELETE /users/1 можно вызвать 10 раз — пользователь всё равно удалён. POST /users каждый раз создаёт нового.
Что такое GraphQL?
GraphQL — язык запросов к API и среда выполнения, разработанная Facebook. В отличие от REST, клиент сам описывает, какие именно данные ему нужны.
Основные операции
| Операция | Аналог в REST | Назначение |
|---|---|---|
query | GET | Получить данные |
mutation | POST/PUT/DELETE | Изменить данные |
subscription | SSE / WebSocket | Получать данные в реальном времени |
query {
user(id: "1") {
name
email
posts {
title
}
}
}Вместо нескольких REST-запросов (/user/1, /user/1/posts) — один запрос, сервер вернёт ровно то, что попросили.
Плюсы GraphQL:
- Нет over-fetching (не получаешь лишние поля)
- Нет under-fetching (не нужно несколько запросов)
- Строгая типизация схемы — автодокументация
- Один endpoint (
/graphql) вместо множества REST-маршрутов
Минусы:
- Сложнее кешировать (всё через
POST) - Порог вхождения выше, чем у REST
- Избыточен для простых API
GraphQL через WebSocket vs HTTP
HTTP-запрос (query / mutation)
Обычный запрос: клиент отправляет запрос, сервер обрабатывает и возвращает ответ. Соединение закрывается.
const response = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: '{ users { name } }' })
});
const { data } = await response.json();WebSocket (subscriptions)
GraphQL-подписки используют постоянное WebSocket-соединение: сервер сам посылает данные клиенту при наступлении события.
import { createClient } from 'graphql-ws';
const client = createClient({ url: 'ws://localhost:4000/graphql' });
client.subscribe(
{ query: 'subscription { messageAdded { text author } }' },
{
next: (data) => console.log('Новое сообщение:', data),
error: (err) => console.error(err),
complete: () => console.log('Подписка завершена'),
}
);| HTTP (query/mutation) | WebSocket (subscription) | |
|---|---|---|
| Соединение | Одноразовое, закрывается после ответа | Постоянное, открытое |
| Направление | Клиент → Сервер → Клиент | Сервер → Клиент (после подписки) |
| Когда использовать | Запрос данных, изменение данных | Реальное время, события |
| Overhead | Минимальный | Постоянное соединение на сервере |
GraphQL-подписки через WebSocket — стандартный способ real-time в GraphQL-стеке. SSE тоже иногда применяют как транспорт для подписок, но WebSocket — исторически основной вариант.
См. также
- realtime — SSE и WebSocket подробнее
- fetch-cors — fetch, CORS, preflight
- http-comparison — методы и версии HTTP