← Назад к вопросам
Какие HTTP-методы являются идемпотентными
1.0 Junior🔥 181 комментариев
#REST API и микросервисы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Идемпотентные HTTP-методы
Идемпотентность в HTTP — это свойство метода, при котором одно и то же действие выполняется много раз с одинаковым результатом. Другими словами, повторные запросы не должны изменять состояние сервера сверх первого запроса.
Какие методы идемпотентны?
GET — Безопасный и идемпотентный
- Не изменяет состояние сервера
- Множественные GET запросы возвращают одинаковый результат
// GET — безопасно идемпотентен
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users/123"))
.GET()
.build();
// Выполни 100 раз — результат идентичный
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
HEAD — Идемпотентен
- Работает как GET, но без тела ответа
- Используется для проверки доступности ресурса
OPTIONS — Идемпотентен
- Запрашивает доступные методы для ресурса
- Не изменяет состояние
PUT — Идемпотентен (при условии)
- Заменяет ресурс целиком
- При повторном запросе с одинаковыми данными результат остаётся прежним
// PUT — идемпотентный
String updatedUser = """
{
"id": "123",
"name": "John Doe",
"email": "john@example.com"
}
""";
HttpRequest putRequest = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users/123"))
.method("PUT", HttpRequest.BodyPublishers.ofString(updatedUser))
.header("Content-Type", "application/json")
.build();
// Выполни дважды — ресурс будет в одинаковом состоянии
client.send(putRequest, HttpResponse.BodyHandlers.ofString());
client.send(putRequest, HttpResponse.BodyHandlers.ofString());
DELETE — Идемпотентен
- Удаляет ресурс
- При повторном запросе: ресурс уже удалён, но логически результат тот же (ресурса нет)
// DELETE — идемпотентный
HttpRequest deleteRequest = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users/123"))
.DELETE()
.build();
// Можешь выполнить дважды безопасно
client.send(deleteRequest, HttpResponse.BodyHandlers.ofString()); // 200 или 204
client.send(deleteRequest, HttpResponse.BodyHandlers.ofString()); // 404, но это нормально
TRACE и CONNECT — Идемпотентны
- Редко используются в практике
- Используются для отладки и установления туннелей
Какие методы НЕ идемпотентны?
POST — Не идемпотентен
- Создаёт новый ресурс
- Каждый запрос может привести к созданию нового объекта
// POST — НЕ идемпотентный
String newUser = """
{
"name": "Jane Doe",
"email": "jane@example.com"
}
""";
HttpRequest postRequest = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.method("POST", HttpRequest.BodyPublishers.ofString(newUser))
.header("Content-Type", "application/json")
.build();
// Выполни дважды — создастся ДВА разных пользователя!
client.send(postRequest, HttpResponse.BodyHandlers.ofString()); // Creates user #1
client.send(postRequest, HttpResponse.BodyHandlers.ofString()); // Creates user #2
PATCH — Обычно не идемпотентен
- Частичное обновление
- В зависимости от операции может быть или не быть идемпотентным
// PATCH — может быть не идемпотентным
String patchData = """
{
"op": "add",
"path": "/tags",
"value": "important"
}
""";
// Каждый запрос добавляет новый тег — не идемпотентно!
Практическое применение
В микросервисах идемпотентность критична для обработки сбоев:
// Клиент с retry логикой
public <T> T executeWithRetry(HttpRequest request, int maxRetries) throws Exception {
for (int i = 0; i < maxRetries; i++) {
try {
return client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException e) {
if (i == maxRetries - 1) throw e;
Thread.sleep(1000 * (i + 1)); // Exponential backoff
}
}
}
// Безопасно использовать для GET и DELETE
executeWithRetry(getRequest, 3);
executeWithRetry(deleteRequest, 3);
// Опасно для POST без дополнительных гарантий
executeWithRetry(postRequest, 3); // Может создать несколько ресурсов!
Ключевые выводы
- Идемпотентные: GET, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT
- Не идемпотентные: POST, PATCH (условно)
- Идемпотентность позволяет безопасно повторять запросы
- Используй PUT для полного обновления и DELETE для удаления
- POST используй только когда нужно создать новый ресурс
- При реализации retry-логики учитывай идемпотентность методов