Модуль 5 · Версии и изменения

Справочник «Стандартизация HTTP API» · модуль 5 · Версии и изменения

Глава 5.3

5.3

Deprecation
и Sunset

Операцию, которой пользуются клиенты, не удаляют сразу: сначала объявляют дату отключения и дают время на переход. В этой главе разобраны пять этапов, через которые проходит операция, и два заголовка, которые предупреждают клиента в каждом ответе.

Категория
Версии
Уровень
Средний
Связанные главы
5.2 Breaking changes · 5.4 CHANGELOG и ADR · 4.3 Заголовки контракта
Зачем это знать
Чтобы убирать лишнее из API, не ломая чужую работу внезапно

§1Пять этапов жизни операции

В учебном проекте порядок записан одной строкой в docs/VERSIONING.md:

docs/VERSIONING.md
ACTIVE → DEPRECATED → MIGRATION PERIOD → SUNSET → REMOVED
ACTIVEОбычная операция. Про неё ничего особенного не сказано, ею пользуются.работает
DEPRECATEDОбъявлена устаревшей. Продолжает работать точно так же, но в описании и в каждом ответе есть предупреждение.работает + предупреждает
MIGRATION PERIODВремя, за которое клиенты переходят на замену. Замена уже существует и описана.ждём
SUNSETНаступила объявленная дата. Операция перестаёт отвечать.дата
REMOVEDОперация убрана из кода и из описания. Только в новой мажорной версии.нет

Между решением убрать операцию и её отключением всегда лежит объявленный срок. Клиент узнаёт этот срок из ответов самого API, а не только из рассылки или документации.

§2Шаг 1: пометка в описании

Первое, что делают, — помечают операцию в описании и объясняют, чем её заменить.

Zalando, правило 187 «MUST reflect deprecation in API specifications»правила компании

«the producers must set deprecated: true for the affected element and add further explanation to the description section of the API specification. If a future shut down is planned, the producer must provide a sunset date and document in details what consumers should use instead and how to migrate.»

Перевод. Владелец API должен указать deprecated: true у затронутого элемента и добавить пояснение в раздел описания спецификации. Если планируется отключение, он должен указать дату отключения и подробно описать, чем потребителям пользоваться вместо него и как перейти.

Обратите внимание, что правило требует трёх вещей сразу: пометки, замены и даты. По пометке без указания замены клиент не может перейти на другую операцию.

app/api/v1/endpoints/tickets.py
@router.get(
    "/open",
    deprecated=True,
    summary="Открытые обращения (устаревшая операция)",
    description="Используйте GET /api/v1/tickets?status=open. Отключение 2027-03-01.",
    operation_id="listOpenTicketsDeprecated",
)
Операция в Swagger UI с перечёркнутым адресом и плашкой deprecated
Как это видит человек. Адрес перечёркнут, рядом плашка deprecated — заметно ещё до раскрытия операции. Это результат одной строки deprecated=True в коде.

§3Шаг 2: заголовки в каждом ответе

Пометки в описании недостаточно: клиентская программа документацию не перечитывает. Поэтому предупреждение помещают в каждый ответ устаревшей операции.

Zalando, правило 189 «SHOULD add Deprecation and Sunset header to responses»правила компании

«During the deprecation phase, the producer should add a Deprecation: <timestamp> (see RFC 9745 section 2) and - if also planned - a Sunset: <date-time> (see RFC 8594 section 3) header on each response affected by a deprecated element»

Перевод. На этапе устаревания владелец API должен добавлять заголовок Deprecation со временем (RFC 9745, раздел 2) и — если отключение тоже запланировано — заголовок Sunset с датой (RFC 8594, раздел 3) в каждый ответ, затронутый устаревшим элементом.

Дальше клиент может действовать сам: библиотека видит заголовок и пишет предупреждение в журнал, мониторинг считает, сколько вызовов устаревших операций осталось до даты отключения. Ни то ни другое невозможно, если предупреждение есть только в документации.

§4Deprecation: RFC 9745

Заголовок отвечает на вопрос «с какого момента операция считается устаревшей». Формат непривычный: знак @ и число секунд Unix.

из настоящего ответа
deprecation: @1789516800
Статус документаRFC 9745, Standards Track, март 2025 года. То есть это полноценный стандарт, а не черновик.стандарт
Что означает значениеМомент времени. Если он в прошлом — операция уже устарела; если в будущем — устареет с этой даты.момент
Почему такой форматЭто тип «Date» из структурированных полей HTTP: знак @ и целое число секунд от начала эпохи Unix.формат
Страница RFC 9745 The Deprecation HTTP Response Header Field на сайте rfc-editor.org
Источник. Документ называется «The Deprecation HTTP Response Header Field». Полезная привычка — открывать первоисточник и проверять статус: у этого заголовка он Standards Track, а у соседнего, как мы сейчас увидим, другой.

§5Sunset: RFC 8594

Второй заголовок отвечает на вопрос «когда перестанет работать». Формат здесь обычный — дата HTTP.

из настоящего ответа
sunset: Mon, 01 Mar 2027 00:00:00 GMT
Deprecation · RFC 9745
  • статус: Standards Track
  • формат: @1789516800
  • смысл: с какого момента устарело
Sunset · RFC 8594
  • статус: Informational
  • формат: Mon, 01 Mar 2027 00:00:00 GMT
  • смысл: когда перестанет отвечать
Что означает статус Informational

Статус Informational означает, что документ описывает сложившуюся практику, а не устанавливает обязательное требование. Пользоваться заголовком это не мешает, но в своём API Style Guide такие случаи отмечают отдельно: когда стандарт необязателен, единственным источником правил остаётся собственный документ проекта. Так же обстоит дело с Idempotency-Key из главы 4.3.

§6Пример целиком

Ниже — настоящий ответ учебного сервиса на вызов устаревшей операции.

GET /api/v1/tickets/open
HTTP/1.1 200
x-request-id: f308afeb-842f-4f14-918d-49be7986e4db
deprecation: @1789516800
sunset: Mon, 01 Mar 2027 00:00:00 GMT
access-control-expose-headers: ETag, Location, X-Request-Id, Retry-After,
                               Deprecation, Sunset, X-RateLimit-Limit, …
content-type: application/json

{ "items": [ … ], "total": 3, "limit": 1, "offset": 0 }
  1. Код 200. Операция работает как прежде — устаревание ничего не сломало.
  2. Два заголовка предупреждения. Программа-клиент может их прочитать и отреагировать.
  3. Оба заголовка перечислены в expose_headers. Иначе веб-клиент их бы не увидел — та же ловушка, что разобрана в главе 4.3.
  4. Тело не изменилось. Клиент, который не собирается ничего делать, продолжает работать до даты отключения.

И четвёртый шаг — запись в журнале изменений, в разделе Deprecated, с указанием замены и даты. Об этом — следующая глава.

CHANGELOG.md · раздел Deprecated
- GET /api/v1/tickets/open — используйте GET /api/v1/tickets?status=open.
  Ответ содержит Deprecation и Sunset; отключение 2027-03-01.

§7Сколько длится период миграции

Стандарты срок не задают — его определяет владелец API, исходя из того, кто его клиенты и как быстро они обновляются.

Кто клиентРазумный срокПочему
Своя же команда, один сервисдниОбновление выкатывается вместе с изменением
Соседние команды в компаниинедели или месяцНужно вписать работу в чужие планы
Мобильное приложениемесяцыПользователи обновляют приложение неделями, часть — никогда
Публичный APIгод и болееКлиентов нельзя ни собрать, ни заставить

В учебном проекте записано «не меньше одного семестра учебного стенда» — срок привязан к тому, как живёт этот конкретный API. Для сравнения: GitHub обещает поддерживать старые редакции не менее двух лет. Сроки отличаются, требование одно — срок объявлен заранее и в явном виде.

Дата — это обещание

Объявив Sunset, вы приняли на себя обязательство: до этой даты операция работает. Перенести дату вперёд (дать больше времени) можно всегда; сдвинуть назад — значит нарушить контракт, даже если формально код ответа не изменился.

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

Удалить операцию сразуКлиенты узнают об этом по ответам 404 в рабочем контуре. Между решением и удалением обязан быть объявленный срок.
Пометка без замены«Не пользуйтесь» без ответа на вопрос «а чем пользоваться» не помогает перейти.
Предупреждение только в документацииПрограмма её не читает. Нужны заголовки в каждом ответе.
Дата отключения только в тексте описанияЕё нельзя прочитать машинно и нельзя посчитать, сколько осталось.
Забыть про expose_headersВеб-клиент не увидит Deprecation и Sunset, и предупреждение до него не дойдёт.
Сдвинуть дату отключения ближеОбъявленный срок — обещание. Продлевать можно, сокращать нельзя.

§9Проверьте себя

  1. Назовите пять этапов жизни операции и скажите, на каком из них клиент впервые получает предупреждение.
  2. Почему пометки deprecated: true в описании недостаточно?
  3. Чем отличаются заголовки Deprecation и Sunset по смыслу, формату и статусу документа?
  4. Что означает значение @1789516800 и почему оно записано именно так?
  5. Почему объявление операции устаревшей — совместимое изменение, а её удаление — нет?
  6. От чего зависит длительность периода миграции? Приведите два разных случая.
ЦепочкаACTIVEDEPRECATEDMIGRATION PERIODSUNSETREMOVED
Что сделатьdeprecated: trueуказать заменуобъявить датузаголовки в ответахзапись в CHANGELOG
ЗаголовкиDeprecation: @секундыSunset: HTTP-date
ИсточникиRFC 9745 — Standards TrackRFC 8594 — InformationalZalando 187, 189

Справочник «Стандартизация HTTP API» · модуль 5 · глава 5.3Макаров Максим Николаевич

Кадр