REST
Основы: API и HTTP. Проектирование: API и интеграции (сквозной пример), модель Ричардсона, маршрут по главам API.
REST
На практике в IT постоянно встречается архитектурный стиль REST. На собеседовании и в код-ревью важно не назвать REST "протоколом" или "библиотекой" — это набор соглашений поверх HTTP и синхронной коммуникации. В микросервисах REST чаще всего — внешний контракт для браузера и мобильных клиентов; внутри кластера дополняют gRPC и GraphQL или очередями. Сравнение трёх стилей на одном примере — REST, GraphQL и gRPC — стили API.
Что такое REST
REST — это просто набор правил, как писать HTTP-запросы так, чтобы тебя понимали другие программисты. Это не технология, не протокол, не библиотека. Это как правила этикета для API.
Любой REST-запрос — это обычный HTTP-запрос. Разница только в том, как программист его составил.
В рабочем проекте REST обсуждают не как "теорию Филдинга", а как качество контракта — стабильные URL, корректные статусы, идемпотентность, понятные ошибки, кэширование и версионирование.
REST (Representational State Transfer) — это архитектурный стиль проектирования сетевых приложений, предложенный Роем Филдингом в его докторской диссертации 2000 года. REST не является протоколом, стандартом или спецификацией. Это совокупность принципов и ограничений, которые задают правила взаимодействия между клиентом и сервером через гипермедиа.
REST опирается на существующие протоколы и технологии, в первую очередь на HTTP. Он использует их семантику максимально эффективно, превращая HTTP из простого транспортного механизма в полноценную платформу для построения масштабируемых, надёжных и легко понимаемых распределённых систем.
Основная идея REST — представление всего, с чем взаимодействует клиент, в виде ресурсов, доступных по уникальным URL. Каждый ресурс имеет своё состояние, которое можно получить, изменить, создать или удалить с помощью стандартных операций.
Принципы REST
REST базируется на шести ключевых ограничениях, которые вместе формируют его архитектурный стиль:
-
Единообразие интерфейса (Uniform Interface)
Все компоненты системы взаимодействуют через единый и предсказуемый интерфейс. Это достигается за счёт:- Идентификации ресурсов в запросах
- Манипуляции ресурсами через представления
- Самоописываемых сообщений
- Гипермедиа как движущей силы состояния приложения (HATEOAS)
-
Отсутствие состояния (Statelessness)
Каждый запрос от клиента к серверу должен содержать всю необходимую информацию для его обработки. Сервер не хранит контекст предыдущих запросов. Это упрощает масштабирование, повышает надёжность и упрощает кэширование. -
Кэшируемость (Cacheability)
Ответы сервера должны явно указывать, могут ли они быть закэшированы. Это позволяет клиентам и промежуточным узлам (например, CDN) эффективно использовать кэш, снижая нагрузку на сервер и ускоряя взаимодействие. -
Клиент-серверная архитектура
Разделение ответственности между клиентом (представление данных, пользовательский интерфейс) и сервером (хранение данных, бизнес-логика). Это обеспечивает независимость их разработки и эволюции. -
Слоистая система (Layered System)
Клиент не знает, взаимодействует ли он напрямую с сервером или через промежуточные слои (прокси, балансировщики, шлюзы). Это упрощает безопасность, масштабируемость и управление. -
Код по требованию (Code on Demand, опционально)
Сервер может передавать исполняемый код (например, JavaScript), который клиент выполняет. Это единственный необязательный принцип REST.
Схема работы REST
Взаимодействие в REST-системе происходит по следующему циклу:
- Клиент отправляет HTTP-запрос к ресурсу по уникальному URL.
- Запрос содержит метод (GET, POST и т.д.), заголовки и, при необходимости, тело.
- Сервер обрабатывает запрос, применяя соответствующую логику.
- Сервер возвращает HTTP-ответ с кодом статуса, заголовками и, при необходимости, телом.
- Клиент интерпретирует ответ и, при необходимости, следует гиперссылкам из тела ответа (HATEOAS).
Этот цикл полностью stateless: каждый запрос независим, и сервер не хранит сессию клиента.
Play ITЗагрузка интерактивного демо…
Инструменты для работы с REST
Postman
Postman — графический инструмент для тестирования и документирования REST API. Он позволяет:
- Отправлять запросы с различными методами, заголовками и телом
- Сохранять коллекции запросов
- Автоматизировать тесты
- Генерировать документацию
- Имитировать серверные ответы (Mock Server)
Swagger (OpenAPI)
Swagger — спецификация для описания REST API в формате OpenAPI. Она позволяет:
- Описывать структуру API в YAML или JSON
- Генерировать интерактивную документацию
- Создавать клиентские SDK автоматически
- Валидировать запросы и ответы
curl
curl — командная утилита для отправки HTTP-запросов из терминала. Примеры:
# Получить список пользователей
curl -X GET https://api.example.com/users
# Создать нового пользователя
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name": "Ivan", "email": "ivan@example.com"}'
# Обновить пользователя
curl -X PUT https://api.example.com/users/123 \
-H "Content-Type: application/json" \
-d '{"name": "Ivan Petrov"}'
Разбор:
curlотправляет HTTP-запрос из терминала: удобно проверить REST-эндпоинт без Postman или Swagger UI. Полная шпаргалка по флагам, auth и health-check — утилита curl, curl / fetch — примеры.
REST-ресурс
REST-ресурс — это любая информация, которая может быть названа и доступна через URI. Ресурс представляет собой абстракцию реального объекта — пользователя, заказа, статьи, файла и т.д.
Каждый ресурс обладает тремя ключевыми свойствами:
- Идентифицируемость — ресурс имеет уникальный URI, по которому его можно найти. Например:
/users/123,/orders/456/items/789. - Модифицируемость — состояние ресурса можно изменить с помощью стандартных операций (POST, PUT, PATCH, DELETE).
- Чётко определённое состояние — в любой момент времени ресурс находится в конкретном состоянии, которое можно получить через GET-запрос.
Ресурс не обязательно соответствует одной записи в базе данных. Это может быть агрегат, представление или даже вычисляемое значение.
Statelessness
Statelessness означает, что сервер не сохраняет состояние взаимодействия с клиентом между запросами. Каждый запрос должен содержать всю необходимую информацию:
- Аутентификационные данные (токен, API-ключ)
- Параметры фильтрации, пагинации
- Данные для создания или обновления ресурса
Преимущества statelessness:
- Масштабируемость — любой сервер в кластере может обработать любой запрос
- Надёжность — сбой одного сервера не влияет на другие
- Простота — нет необходимости управлять сессиями
- Кэшируемость — ответы можно кэшировать без учёта контекста
Если приложению требуется состояние (например, корзина покупок), оно должно храниться на клиенте (в cookies, localStorage) или в базе данных с привязкой к пользователю.
Доступные операции с веб-сервисами
REST использует стандартные HTTP-методы для выполнения CRUD-операций (Create, Read, Update, Delete):
Получение данных (Read)
GET /users
GET /users/123
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
-
Получает представление ресурса или коллекции
-
Не изменяет состояние сервера
-
Безопасный и идемпотентный
Создание новых ресурсов (Create)
POST /users
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
-
Создаёт новый ресурс в коллекции
-
Возвращает
201 Createdс заголовкомLocation, указывающим на URI нового ресурса -
Не идемпотентный: повторный вызов создаёт ещё один ресурс
Обновление ресурсов (Update)
Полное обновление:
PUT /users/123
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
-
Заменяет всё состояние ресурса
-
Идемпотентный: повторный вызов даёт тот же результат
Частичное обновление:
PATCH /users/123
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
-
Изменяет только указанные поля
-
Может быть неидемпотентным, если операция относительна (например, увеличение счётчика)
Удаление ресурсов (Delete)
DELETE /users/123
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
-
Удаляет ресурс
-
Идемпотентный: повторное удаление не вызывает ошибку
HTTP-методы
| Метод | Идемпотентность | Безопасность | Назначение |
|---|---|---|---|
GET | Да | Да | Получение представления ресурса |
POST | Нет | Нет | Создание ресурса или выполнение действия |
PUT | Да | Нет | Полное обновление ресурса |
PATCH | Зависит | Нет | Частичное обновление ресурса |
DELETE | Да | Нет | Удаление ресурса |
HEAD | Да | Да | Получение метаданных без тела |
OPTIONS | Да | Да | Получение поддерживаемых методов |
Идемпотентность — свойство операции, при котором повторный вызов не изменяет результат после первого успешного выполнения.
Безопасность — свойство метода, при котором он не изменяет состояние сервера.
Как определить сервис, метод и HTTP-метод по URL
В правильно спроектированном REST API URL указывает только на ресурс, а не на действие. Метод действия определяется HTTP-глаголом.
Примеры:
GET /users/123
POST /orders
PUT /users/123
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
-
❌
/getUser?id=123— глагол в URL, метод неочевиден -
✅
GET /users/123— ресурс/users/123, методGET -
❌
/createOrder— глагол в URL -
✅
POST /orders— ресурс/orders, методPOST -
❌
/updateUser?id=123— глагол в URL -
✅
PUT /users/123— ресурс/users/123, методPUT
Правильный REST API читается как предложение: "Выполни [метод] над [ресурсом]".
Семантика HTTP
Статус-коды
Статус-коды — неотъемлемая часть контракта API:
-
2xx— успех200 OK— успешный запрос201 Created— ресурс создан204 No Content— успешный запрос без тела ответа
-
4xx— ошибка клиента400 Bad Request— невалидные данные401 Unauthorized— отсутствует аутентификация403 Forbidden— нет прав доступа404 Not Found— ресурс не найден409 Conflict— конфликт при создании/обновлении422 Unprocessable Entity— семантическая ошибка данных
-
5xx— ошибка сервера500 Internal Server Error— необработанное исключение503 Service Unavailable— сервис временно недоступен
Никогда не возвращайте 200 при ошибке — это нарушает контракт.
Runbook — если API "вроде работает", но клиент падает
- Проверьте фактический HTTP-статус и тело ошибки (
4xx/5xx) в Postman/curl. - Сверьте
Content-Type, схему JSON и обязательные поля контракта. - Убедитесь, что для create используется
201 CreatedиLocation, а не "всегда200". - Для повторяемых операций проверьте идемпотентность (
PUT/DELETEи idempotency key для чувствительныхPOST). - Сравните ответ с OpenAPI-описанием и обновите документацию, если контракт эволюционировал.
Такой быстрый чек экономит часы отладки "на клиенте", когда проблема на самом деле в нарушенной семантике API.
Заголовки кэширования
Cache-Control— директивы кэширования (max-age,no-cache,public,private)ETag— идентификатор версии ресурса для условных запросовLast-Modified— дата последнего изменения
Пример условного запроса:
GET /users/123
If-None-Match: "abc123"
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Если ресурс не изменился, сервер вернёт 304 Not Modified.
Идемпотентность
Как уже упоминалось, идемпотентность критична для надёжности:
GET,PUT,DELETE— идемпотентныPOST— не идемпотентенPATCH— может быть идемпотентным, если операции абсолютны
Идемпотентные операции можно безопасно повторять при сетевых ошибках.
URL — правила формирования и составляющие
Общие правила
- Используйте существительные, а не глаголы
- Используйте множественное число для коллекций:
/users,/orders - Стройте иерархию ресурсов:
/users/123/orders/456 - Используйте строчные буквы
- Разделяйте слова дефисами (
kebab-case) или без разделителей
Составляющие URL
https://api.example.com/v1/users/123/orders?status=completed&page=1
│ │ │ │ │ │ │
│ │ │ │ │ │ └── Query parameters
│ │ │ │ │ └── Resource ID
│ │ │ │ └── Sub-resource
│ │ │ └── Collection
│ │ └── Version
│ └── Host
└── Protocol
Разбор:
- Query-параметры фильтруют коллекцию на сервере; каждый ключ должен быть явно разрешён, чтобы избежать произвольных SQL/NoSQL-фильтров.
Шаблоны URL
| Операция | URL | Метод |
|---|---|---|
| Список | /users | GET |
| Создание | /users | POST |
| Получение | /users/123 | GET |
| Обновление | /users/123 | PUT/PATCH |
| Удаление | /users/123 | DELETE |
| Подресурс | /users/123/orders | GET/POST |
Пагинация
Пагинация обязательна для коллекций, которые могут содержать много элементов.
Offset-based (классическая)
GET /orders?page=2&size=20
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Ответ:
{
"Данные": [...],
"pagination": {
"page": 2,
"size": 20,
"total": 150,
"pages": 8
}
}
Разбор:
- JSON показывает формат тела запроса или сообщения в очереди: имена полей должны совпадать с контрактом API или схемой consumer.
Cursor-based (для больших данных)
GET /orders?cursor=abc123&limit=20
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Ответ:
{
"Данные": [...],
"next_cursor": "def456"
}
Разбор:
- JSON показывает формат тела запроса или сообщения в очереди: имена полей должны совпадать с контрактом API или схемой consumer.
Cursor-based устойчива к изменениям в данных во время перелистывания.
Рекомендации
- Устанавливайте
max_size(например, 100) - Возвращайте
400при невалидных параметрах - Документируйте тип пагинации
HATEOAS
HATEOAS (Hypermedia as the Engine of Application State) — принцип, согласно которому клиент переходит от одного состояния к другому, следуя гиперссылкам в ответах сервера.
Пример:
{
"id": 123,
"name": "Ivan",
"_links": {
"self": "/users/123",
"orders": "/users/123/orders",
"update": "/users/123",
"delete": "/users/123"
}
}
Разбор:
- JSON показывает формат тела запроса или сообщения в очереди: имена полей должны совпадать с контрактом API или схемой consumer.
Преимущества HATEOAS:
- Клиент не зависит от жёстко закодированных URL
- API становится самодокументируемым
- Упрощается эволюция API
Недостатки:
- Увеличивает объём ответов
- Сложнее реализовать на клиенте
Resource-Oriented Проектирование
Resource-Oriented Проектирование (ROD) — подход к проектированию API, при котором всё строится вокруг ресурсов:
- Определите основные сущности домена
- Спроектируйте иерархию ресурсов
- Назначьте URI каждой сущности
- Определите допустимые операции для каждого ресурса
- Спроектируйте представления ресурсов
Пример иерархии для интернет-магазина:
/users
/users/{userId}
/users/{userId}/orders
/users/{userId}/orders/{orderId}
/users/{userId}/orders/{orderId}/items
/products
/products/{productId}
Разбор:
- Фрагмент иллюстрирует контракт, конфигурацию или протокол обмена — сверяйте каждую строку с текстом раздела выше.
Версионирование
Версионирование необходимо с самого начала разработки API.
Способы версионирования
- В URL (рекомендуется)
GET /api/v1/users
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
- В заголовке
GET /api/users
Accept: application/vnd.myapi.v1+json
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
- В параметре запроса (не рекомендуется)
GET /api/users?version=1
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Рекомендации
- Используйте major-версии:
v1,v2 - Поддерживайте старые версии минимум 6–12 месяцев
- Документируйте Планы развития deprecation
Фильтрация, сортировка, поиск
Используйте query-параметры для управления представлением коллекций:
GET /users?role=admin&status=active&sort=name&order=desc&q=ivan
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
-
sort— поле для сортировки -
order— направление (asc/desc) -
q— глобальный поиск -
остальные — фильтры по полям
Для сложных фильтров можно использовать специальные синтаксисы:
- OData:
$filter=age gt 18 and status eq 'active' - RSQL:
age>18;status==active
Вложенные ресурсы
Для отношений "один ко многим" используйте вложенность:
GET /users/123/orders
POST /users/123/orders
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Не дублируйте функциональность:
/orders— все заказы/users/123/orders— заказы конкретного пользователя
Избегайте чрезмерной вложенности (более 3 уровней). Для глубоких связей используйте фильтрацию:
- ❌
/companies/1/departments/2/employees/3/Задачи/4 - ✅
/Задачи?employee_id=3
Частичное представление
Позволяет клиенту запрашивать только нужные поля, снижая объём передаваемых данных:
GET /users?fields=id,name,email
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Ответ:
[
{"id": 123, "name": "Ivan", "email": "ivan@example.com"}
]
Разбор:
- JSON показывает формат тела запроса или сообщения в очереди: имена полей должны совпадать с контрактом API или схемой consumer.
Это особенно полезно для мобильных клиентов и медленных соединений.
Частичное представление (Field Selection)
Частичное представление — это возможность клиента указать, какие именно поля ресурса он хочет получить в ответе. Это снижает объём передаваемых данных, ускоряет обработку и уменьшает нагрузку на сеть.
Пример запроса:
GET /users?fields=id,name,email
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Ответ:
[
{
"id": 123,
"name": "Ivan",
"email": "ivan@example.com"
}
]
Разбор:
- JSON показывает формат тела запроса или сообщения в очереди: имена полей должны совпадать с контрактом API или схемой consumer.
Преимущества:
- Экономия трафика для мобильных клиентов
- Снижение нагрузки на сервер при сериализации
- Упрощение логики клиента — получает только нужное
Реализация может быть как простой (разбор строки fields), так и сложной (вложенная выборка — fields=name,orders(id,status)).
Версионирование API
Версионирование — механизм управления изменениями в API, позволяющий поддерживать обратную совместимость и избегать поломки клиентов при обновлениях.
Подходы к версионированию
- В URL (наиболее распространённый)
GET /api/v1/users
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Преимущества — простота, видимость, поддержка прокси и CDN.
Недостатки: нарушает принцип "ресурс один — URI один".
- В заголовке
Accept
GET /api/users
Accept: application/vnd.myapi.v1+json
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Преимущества: чистый URI, соответствует REST.
Недостатки: сложность отладки, неудобство в браузере.
- В параметре запроса (не рекомендуется)
GET /api/users?version=1
Разбор:
-
Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
-
После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Недостатки: нарушает кэшируемость, усложняет маршрутизацию.
Рекомендации
- Используйте major-версии:
v1,v2 - Не версионируйте мелкие изменения (добавление необязательных полей)
- Поддерживайте старые версии минимум 6–12 месяцев
- Документируйте Планы развития deprecation
- Возвращайте заголовок
Deprecation: trueдля устаревших версий
Фильтрация, сортировка, поиск
Эти механизмы позволяют клиенту управлять представлением коллекций без создания отдельных эндпоинтов.
Фильтрация
Передаётся через query-параметры:
GET /users?role=admin&status=active
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Для сложных фильтров можно использовать специализированные синтаксисы:
- OData:
$filter=age gt 18 and status eq 'active' - RSQL:
age>18;status==active
Сортировка
Указывается через параметры sort и order:
GET /users?sort=name&order=desc
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Можно поддерживать множественную сортировку:
GET /users?sort=role,name&order=asc,desc
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Поиск
Глобальный поиск по нескольким полям:
GET /users?q=ivan
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Для продвинутого поиска интегрируется Elasticsearch или аналоги.
Вложенные ресурсы
Вложенные ресурсы отражают иерархические отношения между сущностями.
Пример:
GET /users/123/orders # Заказы пользователя 123
POST /users/123/orders # Создать заказ для пользователя 123
GET /orders/456/items # Позиции в заказе 456
Разбор:
- Прочитайте фрагмент построчно: каждая директива или вызов меняет поведение сервиса, брокера или балансировщика в цепочке микросервисов.
- После правки перезапустите соответствующий процесс или контейнер и проверьте логи, очередь RabbitMQ или ответ HTTP.
Рекомендации
- Используйте вложенность только для отношений "один ко многим"
- Ограничьте глубину вложенности (максимум 3 уровня)
- Для глубоких связей используйте фильтрацию:
- ❌
/companies/1/departments/2/employees/3/Задачи/4 - ✅
/Задачи?employee_id=3
- ❌
- Дублируйте функциональность на корневом уровне:
/orders— все заказы/users/123/orders— заказы конкретного пользователя
HATEOAS
HATEOAS (Hypermedia as the Engine of Application State) — принцип, согласно которому клиент переходит от одного состояния к другому, следуя гиперссылкам, возвращаемым сервером.
Пример ответа:
Код ITЗагрузка примера кода…
Разбор:
- JSON показывает формат тела запроса или сообщения в очереди: имена полей должны совпадать с контрактом API или схемой consumer.
Преимущества
- Клиент не зависит от жёстко закодированных URL
- API становится самодокументируемым
- Упрощается эволюция API — можно менять структуру URI без поломки клиентов
Недостатки
- Увеличивает объём ответов
- Сложнее реализовать на клиенте
- Требует дополнительной логики генерации ссылок
HATEOAS считается продвинутой чертой REST, но не обязательной для большинства современных API.
Resource-Oriented Проектирование (ROD)
Resource-Oriented Проектирование — методология проектирования API, ориентированная на ресурсы как основные строительные блоки.
Этапы проектирования
-
Определите доменные сущности
Пользователь, заказ, товар, категория. -
Спроектируйте иерархию ресурсов
/users
/users/{userId}
/users/{userId}/orders
/orders/{orderId}
/orders/{orderId}/items
Разбор:
- Фрагмент иллюстрирует контракт, конфигурацию или протокол обмена — сверяйте каждую строку с текстом раздела выше.
-
Назначьте URI каждой сущности
Используйте существительные во множественном числе. -
Определите допустимые операции
Для каждого ресурса — набор разрешённых HTTP-методов. -
Спроектируйте представления
Какие поля включать, как форматировать даты, как обрабатывать вложенные объекты.
ROD обеспечивает единообразие, предсказуемость и соответствие принципам REST.
Смежные материалы
- API — интерфейсы прикладного программирования — базовые определения (раздел "Система и сеть")
- Проектирование API и интеграций — контракт, ошибки, версии, пример WMS
- Проектирование API (8.05) — маппинг, мобильные клиенты, rate limit
- Методы и ключ идемпотентности
- Документирование OpenAPI
- Маршрут по всем главам API
Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.