Что такое идемпотентный метод в REST API?

Ответ

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

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

  • GET — только получение данных, не изменяет состояние.
  • PUT — полное обновление ресурса. Повторный запрос с тем же телом не создает побочных эффектов.
  • DELETE — удаление ресурса. После первого успешного удаления ресурс отсутствует, последующие запросы возвращают тот же результат (например, 404).
  • HEAD — аналогичен GET, но без тела ответа.
  • OPTIONS — получение информации о поддерживаемых методах.

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

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

Пример (Java Spring Boot):

@RestController
@RequestMapping("/api/users")
public class UserController {
    // PUT-запрос — идемпотентный
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody UserDto userDto) {
        // Повторный вызов с теми же id и userDto не изменит конечное состояние системы
        User updatedUser = userService.update(id, userDto);
        return ResponseEntity.ok(updatedUser);
    }
}

Почему это важно? Идемпотентность позволяет клиентам безопасно повторять запросы при таймаутах или ошибках (например, 504 Gateway Timeout) без риска дублирования операций (например, двойного списания средств).

Ответ 18+ 🔞

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

Так вот, идемпотентный метод — это такая хитрая жопа, которую можно тыкать сколько угодно раз с одними и теми же данными, а результат будет, будто тыкнули всего один раз. Как будто в стену долбишь: десятый удар ничего нового не принесёт, стена уже сломана. Это, блядь, святое для надёжности, особенно когда эти ебушки-воробушки в сети начинают глючить.

Кто у нас идемпотентные, эти хорошие мальчики:

  • GET — просто посмотрел, ничего не трогал. Идиотобезопасно.
  • PUT — полный апдейт ресурса. Отправил одно и то же десять раз — ресурс после первого раза уже в нужном состоянии, остальные девять просто подтвердят это. Никаких сюрпризов.
  • DELETE — удалил. Послал запрос ещё раз — а ресурса-то уже нет, получишь тот же самый ответ (типа 404), и всё спокойно.
  • HEAD и OPTIONS — это вообще как GET, только ещё более безобидные, информации поддают и всё.

А кто неидемпотентный, этот хулиган:

  • POST — вот этот падла! По умолчанию каждый одинаковый запрос создаёт новую сущность. Отправил данные о пользователе дважды — получишь двух клонов, ёпта. С ним надо осторожно, как с бомбой.

Смотри, как это выглядит в коде (Java Spring Boot):

@RestController
@RequestMapping("/api/users")
public class UserController {
    // PUT-запрос — идемпотентный, его можно повторять
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody UserDto userDto) {
        // Не важно, прилетит этот запрос один раз или пять — юзер с этим id будет обновлён К ОДНОМУ И ТОМУ ЖЕ состоянию.
        User updatedUser = userService.update(id, userDto);
        return ResponseEntity.ok(updatedUser);
    }
}

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