SkillGridИзучай computer science на практике

API: контракт между двумя программами

API — это обещание про имена, форму данных и коды ошибок. Именно оно позволяет двум командам менять свой код, не ломая друг другу работу.

14 мин · 45 XP

В прошлом уроке ты разделил систему на клиента, который спрашивает, и сервер, который отвечает. Как только ты это сделал, появляется новый вопрос: что именно отправляет клиент и что именно приходит в ответ? Теперь вы с клиентом — две разные программы, которые будут обновляться в разные дни, возможно, разные люди и даже в разные годы. Что-то между ними должно оставаться неизменным. Это что-то и есть API.

API (application programming interface) — это контракт, и это слово стоит понимать буквально. Он говорит: если ты отправишь такой запрос, то получишь такой ответ. Не «примерно такой», не «обычно такой». Запрос состоит из четырёх вещей: метод, который говорит, что это за действие (GET читает и ничего не меняет, POST создаёт, DELETE удаляет); путь, который говорит, о какой именно вещи речь (/orders/77); заголовки, которые несут метаданные вроде типа содержимого или токена; и иногда тело с данными. У ответа есть код состояния и, как правило, тело с JSON.

GET    /v1/orders/77      -> 200 OK, one order
POST   /v1/orders         -> 201 Created, the new order
DELETE /v1/orders/77      -> 204 No Content, nothing left
GET    /v1/orders/999     -> 404 Not Found, no such order
POST   /v1/orders/broken  -> 400 Bad Request, the body is wrong
GET    /v1/admin/users    -> 401 Unauthorized, no token sent

Коды состояния — общий язык для результатов, и тебе хватит всего нескольких семейств. 2xx значит, что всё получилось. 4xx значит, что запрос был неправильный: 404 — вещи не существует, 400 — тело запроса бессмысленное, 401 — токена нет или он плохой. 5xx значит, что сервер сломался, пока обрабатывал вполне правильный запрос. Это разделение — не бюрократия; оно подсказывает клиенту, что делать дальше. 404 — это окончательно, повторять не надо. 500 может быть временной ошибкой, и повторить разумно. Без такого разделения каждому клиенту приходится угадывать, и все угадывают по-разному.

Phone appOld server v1New server v2GET /v1/orders/77200 OK, total as a numberthe app was written for v1GET /v2/orders/77200 OK, total as money objectsame field, new shape, app breaksstays on v1 until it is updated

Однажды форму ответа всё же приходится менять. Допустим, total был числом 12.90, а бизнесу теперь нужна ещё и валюта, поэтому total становится объектом. Свою страницу можно обновить в тот же день; а приложение на телефоне — нет, потому что люди месяцами не удаляют старые версии, а скрипт партнёра может обновлять человек, который вообще о тебе не слышал. В этот момент ты и решаешь, ломает ли изменение совместимость. Если каждый существующий клиент, не меняя свой код, теперь сломается — значит, изменение ломающее, и нужна новая версия: /v2/orders/77 рядом со старым /v1/orders/77, и обе работают, пока старую наконец не отключат.

Практика

  1. Твой API возвращает число 12.90 в поле total. Теперь команде нужна ещё и валюта рядом с ним. Какое изменение безопасно?

    Подсказки
    • Ломающее изменение — это такое, из-за которого всем клиентам приходится править код в один и тот же день.
    • Добавлять новое безопасно: старые клиенты просто не замечают поле, которое они никогда не запрашивали.

    13 XP

  2. Сопоставь каждый ответ и ситуацию, которая его вызывает.

    Подсказки
    • Два из этих кодов значат, что сам запрос в порядке, а вот того, что за ним стоит, на месте нет.
    • Читай первую цифру как семейство: 2xx — сработало, 4xx — ты спросил неправильно, 5xx — сломались мы.

    14 XP

  3. Расставь по порядку жизнь контракта API: от первого черновика до вывода из эксплуатации.

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

    18 XP