Какой HTTP метод выбрать для добавления сообщения пользователя и почему
Что проверяют
Понимаете ли вы семантику методов, а не просто помните, что «создание это POST». Следом почти наверняка спросят, что будет, если клиент отправит запрос дважды из-за обрыва сети, и как избежать дубля сообщения.
Как отвечать
Базовый выбор: POST на коллекцию, например POST /chats/{chatID}/messages. Аргументы:
- семантика: POST передаёт данные ресурсу-коллекции, а сервер сам решает, под каким id создать новый элемент;
- не идемпотентен: два одинаковых запроса создают два сообщения, и для чата это нормально, пользователь вправе отправить «ок» дважды;
- ответ:
201 Created, в теле созданное сообщение с id и временем, в заголовкеLocationего адрес.
В Go с версии 1.22 стандартный http.ServeMux понимает метод и параметры в шаблоне: mux.HandleFunc("POST /chats/{chatID}/messages", h), внутри хендлера r.PathValue("chatID"). Запрос другим методом на тот же путь получит 405 Method Not Allowed автоматически.
Сильная часть ответа про повторы. Мобильный клиент не дождался ответа, повторил запрос, и в чате два одинаковых сообщения. Решения:
- ключ идемпотентности: клиент генерирует UUID и шлёт его в заголовке
Idempotency-Keyили в полеclient_message_id. Сервер хранит ключ под уникальным индексом и на повтор возвращает уже созданное сообщение; - PUT с id от клиента:
PUT /chats/{chatID}/messages/{uuid}идемпотентен по определению, повтор запишет тот же ресурс.
Для правки текста подойдёт PATCH, для удаления DELETE.
Где спотыкаются
Передают автора в теле, "userId": 123. Автора сервер берёт из токена сессии, иначе любой отправит сообщение от чужого имени.
Говорят, что PUT нельзя использовать для создания. Можно, если клиент сам знает адрес ресурса, и это как раз способ получить идемпотентность.
Выбирают GET с текстом в query-параметрах «потому что проще». GET обязан быть безопасным, его повторяют прокси и браузеры, а URL с текстом сообщения оседает в логах.