Какие принципы построения REST API существуют?
Что проверяют
Умеете ли вы превратить общие слова про REST в работающий HTTP-сервис на Go: ресурсы, методы, коды, ошибки, повторы запросов. Следом часто просят показать роутинг на стандартной библиотеке и объяснить, как защититься от двойного создания заказа, если клиент повторил запрос.
Как отвечать
Коротко назовите основу: REST это архитектурный стиль с ограничениями клиент-сервер, stateless, кэшируемость, единообразный интерфейс и многоуровневость. Дальше то, что реально проверяют в Go-команде:
- ресурсы и URL: существительные во множественном числе, вложенность для связей:
/users/{id}/orders. Глаголы в пути не нужны, действие задаёт метод; - роутинг: с Go 1.22 стандартный
http.ServeMuxпонимает метод и параметры:mux.HandleFunc("GET /users/{id}", h), значение достаётся черезr.PathValue("id"). До этого ради такого почти всегда брали chi, gin или echo; - идемпотентность:
GET,PUT,DELETEидемпотентны, повтор даёт тот же итог на сервере, что и один вызов.POSTнет, поэтому для платежей и заказов вводят заголовокIdempotency-Keyи хранят результат по ключу; - коды и ошибки:
201сLocationна создание,204без тела,400на невалидный ввод,404,409на конфликт версий. Тело ошибки в едином формате, напримерapplication/problem+json; - пагинация: для живых данных курсор надёжнее
offset, записи не пропадают и не дублируются между страницами; - таймауты: у
http.Serverпо умолчаниюReadTimeoutиWriteTimeoutнулевые, то есть бесконечные, их задают явно, а работу отменяют черезr.Context().
Где спотыкаются
Говорят, что идемпотентный метод «не меняет состояние». Первый DELETE меняет, идемпотентность про то, что повторы ничего сверх этого не добавляют, при этом второй вызов может честно вернуть 404.
Вызывают w.WriteHeader после записи тела или ставят заголовки после WriteHeader. В первом случае уйдёт 200, а в лог попадёт «superfluous response.WriteHeader call», во втором заголовки просто потеряются.
Кодируют JSON прямо в w и уже после этого узнают об ошибке. Статус к тому моменту отправлен, поэтому ответ, который может упасть при сборке, сначала пишут в буфер.