Что такое идемпотентность в контексте HTTP и какие методы являются идемпотентными?

Ответ

Идемпотентность — это свойство операции, при котором повторное её выполнение с теми же входными данными не изменяет конечное состояние системы после первого успешного выполнения. В контексте HTTP API это означает, что многократная отправка одного и того же запроса приводит к тому же результату, что и однократная.

Это критически важно для надежности сетевых взаимодействий, так как клиент может безопасно повторить запрос в случае сбоя сети, не опасаясь создания дубликатов или некорректных изменений данных.

Идемпотентные HTTP-методы

  • GET, HEAD, OPTIONS, TRACE Эти методы считаются "безопасными", так как они предназначены только для чтения данных и не должны изменять состояние сервера. Следовательно, они по определению идемпотентны.

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

    # Первый запрос создает или обновляет ресурс
    PUT /users/123 HTTP/1.1
    Content-Type: application/json
    
    { "name": "Alice", "email": "alice@example.com" }
    
    # Повторный запрос приведет к тому же состоянию ресурса
    PUT /users/123 HTTP/1.1
    Content-Type: application/json
    
    { "name": "Alice", "email": "alice@example.com" }
  • DELETE Удаляет ресурс. Первый запрос удалит ресурс, а последующие запросы к тому же ресурсу просто подтвердят, что он уже удален (обычно возвращая 404 Not Found). Состояние системы ("ресурс удален") не изменится.

Неидемпотентные HTTP-методы

  • POST Обычно используется для создания нового ресурса. Каждый успешный POST-запрос создает новую сущность с уникальным идентификатором, изменяя состояние системы.

    • POST /users -> создает пользователя с ID 1.
    • POST /users (тот же запрос) -> создает пользователя с ID 2.
  • PATCH Применяет частичные изменения к ресурсу. Идемпотентность PATCH-запроса зависит от самой операции.

    • Идемпотентный PATCH: PATCH /users/123 с телом {"email": "new@example.com"}. Повторные вызовы не изменят email.
    • Неидемпотентный PATCH: PATCH /articles/1 с телом {"action": "increment_views"}. Каждый вызов будет увеличивать счетчик просмотров.

Ответ 18+ 🔞

А, слушай, про идемпотентность! Ну это ж такая штука, блядь, которая, если её ебануть сто раз, результат будет как от одного раза, а не как от ста. Представь, ты на кнопку лифта нажимаешь — хуй с ним, хоть десять раз ткни, он всё равно на один этаж поедет, а не на десять. Вот и вся философия, в рот меня чих-пых!

В апишках это вообще святое, потому что интернет — он, сука, такой ненадёжный, как моя бывшая. Отправил запрос, а он потерялся. Ну и что делать? Правильно, отправить ещё раз. И вот тут, если метод не идемпотентный, можно так наворотить, что потом полжизни разгребать. Создашь сто одинаковых пользователей, блядь, или счётчик лайков накрутишь до овердохуища.

Безопасные ребята (читай: идемпотентные по умолчанию):

  • GET, HEAD, OPTIONS, TRACE — это такие скромняги. Они только смотрят, ничего не трогают. Их можно вызывать до посинения, хуйня какая-то случится.

Главные идемпотентные мужики:

  • PUT — это такой максималист, блядь. "Всё по-новой, нахуй старое!" Отправишь один раз — он ресурс перезапишет. Отправишь десять раз с тем же телом — он десять раз перезапишет тем же самым. В итоге состояние — как после первого раза. Чистая идемпотентность, ёпта!

    PUT /users/123 HTTP/1.1
    Content-Type: application/json
    
    { "name": "Alice", "email": "alice@example.com" }

    Сделал раз — Алиса есть. Сделал сто раз — Алиса на месте. Всё логично.

  • DELETE — ну тут вообще пиздец просто. Удалил ресурс — иди нахуй. Позвал его ещё раз — он уже удалён, иди нахуй. Состояние системы не меняется: ресурс как был в пизду, так и остался.

А вот эти — подозрительные, блядь (чаще неидемпотентные):

  • POST — это ж чистой воды креативщик, ёбаный в рот! Каждый раз он норовит создать что-то новое. Отправил POST /users — получил юзера с ID 1. Отправил ещё раз — получил его клона с ID 2. Вот тебе и дубли, вот тебе и пиздец в базе данных.

  • PATCH — а вот это хитрая жопа, блядь. Он как повернётся. Если он просто статичное поле меняет, то да, идемпотентный.

    • PATCH /users/123 с {"email": "new@mail.ru"} — поменял почту, второй раз меняет на ту же самую. Ну и хуй с ним. А вот если он, сука, действие выполняет, то тут уже терпения ноль ебать.
    • PATCH /articles/1 с {"action": "increment_views"} — это же ёперный театр! Каждый вызов — +1 к просмотрам. Нажал сто раз из-за глюков сети — статья стала мегавирусной, хотя её нихуя не читали.

Короче, суть в чём: проектируя апишку, думай башкой, э! Где можно — делай идемпотентным. Чтобы клиент, если что, мог без страха повторить запрос и не накосячить. А то получится как в том анекдоте: "отправил POST на платёж, интернет заглючил — нажал ещё раз пять... теперь я банкрот, блядь".