Какие знаешь неидемпотентные методы HTTP?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Неидемпотентные методы 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()
Как обеспечить безопасность при неидемпотентных методах
- 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}
)
# Сервер может закэшировать результат и вернуть тот же ответ для повторного запроса с тем же ключом
- 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, правильно обрабатывать ошибки и избегать слепых повторов запросов.