Какие HTTP-методы являются идемпотентными и почему?

Ответ

Идемпотентный HTTP-метод — это метод, многократное выполнение которого с одними и теми же данными приводит к одинаковому результату на сервере. Состояние сервера после первого успешного запроса не меняется при последующих идентичных запросах.

Список идемпотентных методов:

Метод Объяснение идемпотентности
GET Только получает данные. Не изменяет состояние ресурса. Повторные вызовы возвращают один и тот же ответ (если данные не изменились другим способом).
HEAD Аналогичен GET, но возвращает только заголовки ответа без тела.
PUT Используется для полного обновления ресурса по известному URI. Повторная отправка одного и того же запроса PUT завершится с тем же результатом: ресурс будет иметь состояние, описанное в первом запросе.
DELETE Удаляет ресурс. После первого успешного вызова ресурс удален. Последующие вызовы вернут тот же результат (например, 404 Not Found или 410 Gone), не изменяя состояние системы дальше.
OPTIONS Возвращает поддерживаемые методы для ресурса. Не изменяет состояние.

Пример идемпотентности PUT:

PUT /api/users/123 HTTP/1.1
Content-Type: application/json

{"name": "Alice", "role": "admin"}

Сколько бы раз ни был отправлен этот запрос, пользователь с id=123 в итоге будет иметь имя "Alice" и роль "admin". Не создастся новых пользователей.

Неидемпотентные методы:

  • POST: Используется для создания ресурса. Каждый вызов POST создает новый ресурс, что приводит к разному состоянию сервера.

    POST /api/users HTTP/1.1
    Content-Type: application/json
    
    {"name": "Bob"}

    Повторные вызовы создадут несколько пользователей с именем "Bob".

  • PATCH: Часто неидемпотентен, так как используется для частичного обновления. Результат может зависеть от текущего состояния ресурса. Например, инкремент счетчика ({"op": "increment", "path": "/counter"}) при каждом вызове даст разный результат.

Важность для тестирования: Понимание идемпотентности критично для:

  • Тестирования надежности: Проверка, что повторная отправка запроса (например, из-за таймаута сети) не приводит к некорректному состоянию (двойное списание, создание дублей).
  • Проектирования API: GET, PUT, DELETE должны быть идемпотентными для предсказуемости работы API.

Ответ 18+ 🔞

Да ты посмотри, что эти умники в RFC нагородили! Сидят, блядь, в своих башнях из слоновой кости, придумывают термины, от которых мозг вскипает, как чайник у бабки Зины. «Идемпотентный», ёпта! Звучит, как диагноз в психушке. А на деле-то всё просто, как три копейки.

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

Давай разберём эту зоопарк методов, а то я чувствую, терпения ноль ебать.

GET — это как спросить у соседа: «Дядя Вова, а что в холодильнике?». Сколько ни спрашивай, он будет бубнить одно и то же: «Селедка под шубой, водка и тоска». Пока его баба не сходит в магазин, состояние его холодильника неизменно. Идемпотентный, сука.

HEAD — это тот же самый вопрос, но дядя Вова такой хитрожопый, только глазами в сторону холодильника покосится и кивнёт: «Да там всё есть». Тела ответа нет, но суть та же.

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

DELETE — это когда ты, наконец, не выдерживаешь и выкидываешь его холодильник в окно. Бах! Разбился. Подойдёшь к окну через час — что видишь? Разбитый холодильник. Подойдёшь через день — тот же пиздец. Состояние «холодильника нет» достигнуто. И больше не меняется. Идемпотентный.

OPTIONS — это спросить у дяди Вовы: «А что мне с тобой вообще можно сделать? Поговорить? Плюнуть? По морде дать?». Он перечислит. Спрашивай хоть сто раз — список его возможностей не изменится от самого вопроса.

А теперь, внимание, главные возмутители спокойствия:

POST — это, блядь, полный пиздец. Это как прийти к дяде Вове и сказать: «Знаешь что, я тут тебе ребёночка заведу». Каждый раз, когда ты это произносишь, в его жизни появляется новый орущий сральник. Один запрос — один ребёнок. Десять запросов — десять детей, ебать его в сраку! Состояние его квартиры меняется кардинально с каждым разом. Неидемпотентный, как мать его.

PATCH — это штука похитрее. Это как сказать: «Дядя Вова, увеличь количество детей в квартире на одного». Первый раз скажешь — станет двое. Второй раз — трое. Результат зависит от того, в каком состоянии ты его застал. Тоже неидемпотентная сволочь.

И вот зачем это всё нужно нам, простым смертным? А затем, чувак, что сеть — она ненадёжная сука. Ты отправил запрос, а он потерялся, как носки в стиральной машине. Клиент думает: «Бля, не дошло!», и шлёт его снова. А на сервере уже всё отработало. Если метод был неидемпотентный, как POST, то получится, что ты не одного ребёнка дяде Вове завёл, а двух! Двойное списание денег, дублирование заказа — вот это всё, пиздец и хаос.

Поэтому, когда проектируешь своё API, держи в голове: GET, PUT, DELETE — должны быть предсказуемыми, как восход солнца. Отправь их хоть сто раз — результат на сервере должен быть один и тот же. Это как закон природы, блядь. Нарушишь — получишь ебаный legacy-код, который все боятся трогать, и ночные кошмары про дубли в базе.

Вот и вся философия. Не так страшен чёрт, как его матерное описание.