REST и проектирование API
REST и проектирование Web API: ресурсы, глаголы, предсказуемые URL.
Суть: REST — это стиль проектирования API, где данные представлены как ресурсы (пользователи, заказы), доступные по понятным URL, а действия над ними выражены HTTP-глаголами (GET, POST, PUT, DELETE). Хороший REST-API предсказуем: по URL и методу ясно, что произойдёт.
Web API — это бэкенд без HTML, отдающий данные (обычно JSON) для фронтенда, мобильных приложений или других сервисов. REST задаёт правила, как такой API проектировать, чтобы он был понятным и единообразным.
Ресурсы и глаголы
| Метод | URL | Действие |
|---|---|---|
| GET | /api/users | Список пользователей |
| GET | /api/users/42 | Один пользователь |
| POST | /api/users | Создать пользователя |
| PUT | /api/users/42 | Обновить целиком |
| DELETE | /api/users/42 | Удалить |
Заметьте: URL — это существительные (ресурсы), действие задаёт глагол (HTTP-метод). Не делайте /api/getUser или /api/deleteUser?id=42 — это анти-REST.
Идемпотентность и безопасность
GET — безопасный (не меняет данные) и идемпотентный. PUT и DELETE — идемпотентные (повтор даёт тот же результат). POST — нет: два POST создадут два ресурса. Это влияет на ретраи и кэширование.
Как работает под капотом
Когда клиент шлёт POST /api/users с JSON-телом, ASP.NET Core десериализует тело в C#-объект (DTO), валидирует его, передаёт в ваш метод. Вы создаёте ресурс и возвращаете 201 с заголовком Location, указывающим на новый ресурс. Клиент по этому заголовку знает, где забрать созданную сущность. Так REST остаётся самоописательным: ответы содержат не только данные, но и навигацию.
Частые ошибки
- Глаголы в URL.
/api/createUserвместоPOST /api/users— нарушает REST и путает. - Неправильный метод. Удаление через GET опасно: поисковые боты и префетч могут «удалить» данные.
- Игнорировать идемпотентность. Делать POST идемпотентным «вручную» без понимания — источник дубликатов.
Best practices
- Множественное число для коллекций:
/users,/orders. - Вложенность для связей:
/users/42/orders. - Версионируйте API (
/api/v1/users), чтобы менять контракт без поломки клиентов.
Уровни зрелости REST и где остановиться
Существует модель зрелости Ричардсона: уровень 0 — один URL и POST на всё, уровень 1 — отдельные ресурсы, уровень 2 — корректное использование HTTP-глаголов и кодов, уровень 3 — гипермедиа (HATEOAS, ссылки на связанные действия прямо в ответах). На практике большинство качественных API живут на уровне 2: ресурсы-существительные, правильные глаголы и статус-коды. Уровень 3 встречается реже — он мощный, но усложняет и сервер, и клиентов, поэтому добавляют его осознанно.
Хороший REST-дизайн — это ещё и продуманные детали: пагинация коллекций (через ?page=2&size=20), фильтрация и сортировка (?status=active&sort=name), частичное обновление через PATCH вместо полного PUT. Эти соглашения делают API предсказуемым: разработчик клиента, увидев одну вашу ручку, угадывает поведение остальных.
Версионирование и устойчивость контракта
API живёт долго, а клиенты обновляются не сразу, поэтому ломать контракт нельзя. Решение — версионирование: /api/v1/users, /api/v2/users, либо версия в заголовке. Старые клиенты продолжают ходить в v1, новые — в v2. Внутри одной версии действует правило обратной совместимости: добавлять поля можно, удалять и переименовывать — нельзя. Это дисциплина, без которой публичный API быстро превращается в источник поломок у потребителей.
Наконец, REST-ответы должны быть самоописательными в разумных пределах: при создании ресурса возвращайте заголовок Location и тело созданной сущности, при ошибке — понятную структуру (ProblemDetails). Чем меньше клиенту приходится «додумывать» по недокументированным признакам, тем надёжнее интеграция. Предсказуемость — главная ценность REST, важнее формальной чистоты.
Итог: REST делает API предсказуемым через ресурсы-существительные и глаголы-методы. Дальше — как принимать и валидировать входные данные.