← Назад к вопросам

Какие знаешь неидемпотентные методы HTTP?

1.0 Junior🔥 151 комментариев
#REST API и HTTP

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

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

Основные неидемпотентные методы

1. POST — самый классический пример

При отправке POST запроса каждый повторный запрос с одинаковыми данными создаёт новый ресурс на сервере.

# Каждый вызов создаёт новую запись
response1 = requests.post("https://api.example.com/orders", json={"item": "laptop", "amount": 1500})
response2 = requests.post("https://api.example.com/orders", json={"item": "laptop", "amount": 1500})
# На сервере теперь 2 одинаковых заказа с разными ID

2. PATCH — частичное изменение

METHOD для неполного обновления ресурса. В зависимости от реализации может быть неидемпотентным, если операция зависит от текущего состояния.

# Пример неидемпотентного PATCH
response = requests.patch("https://api.example.com/users/123", json={"$increment": {"visits": 1}})
# Каждый вызов увеличивает счётчик на 1

3. DELETE — может быть неидемпотентным в определённых сценариях

В стандартной реализации DELETE идемпотентен (удаление несуществующего ресурса вернёт 404 оба раза), но в некоторых специфических случаях может быть неидемпотентным.

# Обычно идемпотентен
response1 = requests.delete("https://api.example.com/users/123")  # 204 No Content
response2 = requests.delete("https://api.example.com/users/123")  # 404 Not Found

Сравнение с идемпотентными методами

МетодИдемпотентностьПримечание
GETИдемпотентенНе изменяет состояние сервера
HEADИдемпотентенКак GET, но без тела ответа
OPTIONSИдемпотентенПросто возвращает информацию
PUTИдемпотентенПолное замещение ресурса
DELETEИдемпотентенСтандартная реализация
POSTНеидемпотентенСоздаёт новый ресурс каждый раз
PATCHМожет быть обоимЗависит от реализации

Практические последствия

import requests
from typing import Any

def create_order(item: str, amount: float) -> dict:
    """POST запрос — неидемпотентен"""
    response = requests.post(
        "https://api.example.com/orders",
        json={"item": item, "amount": amount}
    )
    return response.json()

# Если происходит timeout или network error, часто переотправляют запрос
# Это может привести к дублированию заказов
for _ in range(3):
    try:
        order = create_order("laptop", 1500)
        break
    except requests.RequestException:
        continue  # Переотправляем — создаём новый заказ!

def update_user(user_id: int, increment_field: str) -> dict:
    """PATCH с инкрементом — неидемпотентен"""
    response = requests.patch(
        f"https://api.example.com/users/{user_id}",
        json={"$increment": {increment_field: 1}}
    )
    return response.json()

# Безопаснее использовать PUT для замещения
def update_user_safe(user_id: int, **kwargs) -> dict:
    """PUT — идемпотентен"""
    response = requests.put(
        f"https://api.example.com/users/{user_id}",
        json=kwargs
    )
    return response.json()

Как обеспечить безопасность при неидемпотентных методах

  1. Idempotency Key — уникальный ключ в заголовке
import uuid

idempotency_key = str(uuid.uuid4())
response = requests.post(
    "https://api.example.com/orders",
    json={"item": "laptop", "amount": 1500},
    headers={"Idempotency-Key": idempotency_key}
)
# Сервер может закэшировать результат и вернуть тот же ответ для повторного запроса с тем же ключом
  1. Retry с экспоненциальной задержкой — для идемпотентных методов
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def fetch_data():
    response = requests.get("https://api.example.com/data")
    response.raise_for_status()
    return response.json()

Заключение

Основной неидемпотентный метод — POST, который создаёт новый ресурс каждый раз. PATCH может быть неидемпотентным при определённых операциях (инкремент, конкатенация). При работе с неидемпотентными методами важно использовать Idempotency Key, правильно обрабатывать ошибки и избегать слепых повторов запросов.