Зачем API нужно версионирование

API эволюционируют: добавляются функции, меняются модели данных, заменяются старые паттерны. Без версионирования любое изменение может сломать существующих клиентов. Версионирование позволяет несовместимым изменениям сосуществовать со старыми версиями.

Breaking vs. Non-Breaking изменения

Non-breaking (безопасны без новой версии):

  • Добавление опциональных полей в ответы
  • Добавление новых endpoint-ов
  • Добавление опциональных query-параметров
  • Ослабление правил валидации

Breaking (требуют новой версии):

  • Удаление или переименование поля
  • Изменение типа данных поля
  • Превращение опционального поля в обязательное
  • Изменение структуры URL
  • Изменение механизмов аутентификации

Стратегии версионирования

Версионирование через URL Path

Самый распространённый подход:

GET /api/v1/users
GET /api/v2/users

Плюсы: Легко видеть, кешировать, маршрутизировать Минусы: URL меняется между версиями

Версионирование через заголовки

GET /api/users
Accept: application/vnd.myapi.v2+json

Плюсы: Чистые URL Минусы: Скрыто, сложнее отлаживать

Версионирование через Query Parameter

GET /api/users?version=2

Плюсы: Легко переключать, видно в URL Минусы: Путаница с фильтрацией, проблемы кеширования

Сравнение

АспектURL PathHeaderQuery Param
ВидимостьВысокаяНизкаяСредняя
КешированиеПростоСложноСложно
Маршрутизация в gatewayПростоУмеренноУмеренно
Тестирование в браузереПростоСложноПросто
РаспространённостьМаксимальнаяСредняяНизкая

Тестирование версионирования API

Тесты обратной совместимости

Для каждой новой версии проверяйте:

  1. Структура ответа: Клиенты v1 получают формат v1
  2. Наличие полей: Поля v1 не удалены
  3. Типы данных: Без изменений типов в v1
  4. Формат ошибок: Ответы об ошибках v1 без изменений
  5. Аутентификация: Механизмы v1 работают

Тесты по версиям

Тестv1v2
GET /users{name: "Alice"}{firstName: "Alice", lastName: "..."}
Пагинация?page=1&per_page=20?cursor=abc&limit=20
Формат ошибок{error: "Not found"}{error: {code: "NOT_FOUND", message: "..."}}

Тестирование устаревания

При устаревании версии проверяйте:

  1. Заголовки устаревания:
Deprecation: true
Sunset: Sat, 01 Mar 2026 00:00:00 GMT
Link: </api/v2/docs>; rel="successor-version"
  1. Заголовки предупреждений с информацией об устаревании
  2. Ссылки на документацию в ответе или заголовках
  3. Сроки прекращения: Устаревшая версия работает до указанной даты
  4. После прекращения: Возвращает 410 Gone или перенаправляет

Поведение версии по умолчанию

Что происходит без указания версии:

  • API использует последнюю версию?
  • API использует v1 (безопаснее для совместимости)?
  • API возвращает ошибку, требуя явную версию?

Консистентность данных между версиями

Данные из v1 должны быть доступны в v2:

1. POST /api/v1/users → Создать пользователя (формат v1)
2. GET /api/v2/users/{id} → Должен вернуть формат v2
3. PUT /api/v2/users/{id} → Обновить в формате v2
4. GET /api/v1/users/{id} → Должен вернуть формат v1

Тестирование миграции

При переходе с v1 на v2:

  • Проверить наличие v2-эквивалентов для всех функций v1
  • Протестировать трансформацию данных v1 в ответах v2
  • Проверить документированные альтернативы удалённых функций
  • Убедиться, что токены работают в обеих версиях

Распространённые баги версионирования

БагКак обнаружить
v1 содержит поля v2Сравнить схему v1 с документацией
v2 ломает контракт v1Запустить тесты v1 на текущем деплое
Нет уведомления об устареванииПроверить заголовки устаревших версий
Несогласованность данныхСоздать в v1, прочитать в v2, сравнить
Версия по умолчанию меняетсяТестировать запросы без явной версии

Практическое упражнение

  1. Сравните версии: Сравните одну и ту же операцию в разных версиях API.
  2. Проверьте совместимость: Отправляйте запросы к обеим версиям, проверяйте данные.
  3. Создайте чек-лист миграции: Для гипотетической миграции v1 → v2 перечислите все изменения.
  4. Проверьте устаревание: Найдите deprecated endpoint и проверьте заголовки.

Ключевые выводы

  • Версионирование позволяет несовместимым изменениям сосуществовать со старыми версиями
  • URL path versioning — самый распространённый; header versioning — наиболее REST-совместимый
  • Breaking changes требуют новых версий; non-breaking — нет
  • Тестируйте обратную совместимость, запуская старые тесты на новых деплоях
  • Проверяйте коммуникацию устаревания: заголовки, даты, документацию и руководства по миграции