API: контракт между двумя программами
API — это обещание про имена, форму данных и коды ошибок. Именно оно позволяет двум командам менять свой код, не ломая друг другу работу.
В прошлом уроке ты разделил систему на клиента, который спрашивает, и сервер, который отвечает. Как только ты это сделал, появляется новый вопрос: что именно отправляет клиент и что именно приходит в ответ? Теперь вы с клиентом — две разные программы, которые будут обновляться в разные дни, возможно, разные люди и даже в разные годы. Что-то между ними должно оставаться неизменным. Это что-то и есть 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 может быть временной ошибкой, и повторить разумно. Без такого разделения каждому клиенту приходится угадывать, и все угадывают по-разному.
Однажды форму ответа всё же приходится менять. Допустим, total был числом 12.90, а бизнесу теперь нужна ещё и валюта, поэтому total становится объектом. Свою страницу можно обновить в тот же день; а приложение на телефоне — нет, потому что люди месяцами не удаляют старые версии, а скрипт партнёра может обновлять человек, который вообще о тебе не слышал. В этот момент ты и решаешь, ломает ли изменение совместимость. Если каждый существующий клиент, не меняя свой код, теперь сломается — значит, изменение ломающее, и нужна новая версия: /v2/orders/77 рядом со старым /v1/orders/77, и обе работают, пока старую наконец не отключат.
Практика
Твой API возвращает число 12.90 в поле total. Теперь команде нужна ещё и валюта рядом с ним. Какое изменение безопасно?
Подсказки
- Ломающее изменение — это такое, из-за которого всем клиентам приходится править код в один и тот же день.
- Добавлять новое безопасно: старые клиенты просто не замечают поле, которое они никогда не запрашивали.
13 XP
Сопоставь каждый ответ и ситуацию, которая его вызывает.
Подсказки
- Два из этих кодов значат, что сам запрос в порядке, а вот того, что за ним стоит, на месте нет.
- Читай первую цифру как семейство: 2xx — сработало, 4xx — ты спросил неправильно, 5xx — сломались мы.
14 XP
Расставь по порядку жизнь контракта API: от первого черновика до вывода из эксплуатации.
Подсказки
- Ничего нельзя построить, пока обе стороны не договорились, что означают слова.
- Номера версий нужны, чтобы старые клиенты продолжали работать, поэтому отключают всегда в самом конце.
18 XP