Может ли метод POST стать идемпотентным и как
Что проверяют
Различаете ли вы семантику метода по спецификации и поведение конкретного API, и сможете ли это проверить. Следом обычно просят составить набор тестов для создания платежа или заказа.
Как отвечать
По RFC 9110 POST не идемпотентен: спецификация не обещает, что повтор не создаст второй ресурс. Идемпотентны, например, GET, PUT и DELETE. Но сервер вправе обрабатывать POST идемпотентно, и в платёжных API это норма: клиент при таймауте не знает, дошёл ли запрос, и повторяет его.
Способы:
- ключ идемпотентности: клиент генерирует UUID и шлёт его в заголовке
Idempotency-Key. Сервер хранит ключ, отпечаток тела и ответ, а на повтор отдаёт сохранённый ответ без повторного действия. Для заголовка есть черновик стандарта IETF; - естественный ключ: клиент передаёт свой номер заказа, на нём в базе уникальный индекс, и дубль возвращает уже созданную запись.
Идемпотентность описывает состояние сервера, а не одинаковый код ответа: повторный DELETE может вернуть 404 и остаётся идемпотентным.
Что проверять:
- повтор с тем же ключом: ресурс один, ответ совпадает с первым, письмо или списание случилось один раз;
- тот же ключ, другое тело: ожидается ошибка, по черновику 422;
- параллельные запросы: два одновременных запроса с одним ключом через k6, JMeter или потоки в pytest, по черновику второй получает 409;
- обрыв ответа: через Charles или mitmproxy отбросить ответ, повторить запрос и убедиться, что дубля нет;
- срок жизни ключа: что происходит после истечения и описано ли это в документации.
Где спотыкаются
Отвечают, что POST идемпотентным быть не может в принципе. Спецификация этого не гарантирует, но реализация на сервере возможна и распространена.
Проверяют только статус ответа. Нужно смотреть в базу и на побочные эффекты: два списания при двух ответах 200 это проваленный тест.
Забывают про гонку. Последовательный повтор проходит, а два одновременных запроса создают два заказа, потому что проверка ключа и запись не атомарны.