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

«Что такое идемпотентность в контексте HTTP и какие методы являются идемпотентными?» — вопрос из категории Архитектура, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Идемпотентность — это свойство операции, при котором повторное её выполнение с теми же входными данными не изменяет конечное состояние системы после первого успешного выполнения. В контексте 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"}. Каждый вызов будет увеличивать счетчик просмотров.