Что такое идемпотентные методы HTTP?

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

Ответ

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

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

  • GET, HEAD, OPTIONS, TRACE: Запросы только для чтения. Они не изменяют состояние сервера, поэтому по определению идемпотентны.
  • PUT: Используется для полного обновления ресурса. Повторные запросы с тем же телом к одному URI должны оставлять ресурс в идентичном состоянии.
  • DELETE: Удаление ресурса. После первого успешного удаления ресурса, последующие запросы DELETE к тому же URI обычно возвращают статус 404 Not Found или 410 Gone, но общее состояние сервера (отсутствие ресурса) не меняется.

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

  • POST: Предназначен для создания ресурсов или выполнения действий с побочными эффектами. Каждый запрос POST может создать новый ресурс или привести к иному изменению состояния.

Пример на PHP с использованием Guzzle HTTP Client:

// Идемпотентный PUT-запрос (обновление пользователя)
$client = new GuzzleHttpClient();
$response1 = $client->put('https://api.example.com/users/123', [
    'json' => ['name' => 'Alice', 'role' => 'admin']
]);
// Если этот запрос отправить повторно из-за таймаута, это безопасно.
$response2 = $client->put('https://api.example.com/users/123', [
    'json' => ['name' => 'Alice', 'role' => 'admin']
]);
// Состояние пользователя с ID 123 после обоих запросов идентично.

// Неидемпотентный POST-запрос (создание пользователя)
$response3 = $client->post('https://api.example.com/users', [
    'json' => ['name' => 'Bob']
]); // Создаёт пользователя с ID 456
$response4 = $client->post('https://api.example.com/users', [
    'json' => ['name' => 'Bob']
]); // Создаёт ЕЩЁ ОДНОГО пользователя с ID 457 — это дублирование!

Важное уточнение: Идемпотентность относится к состоянию ресурса на сервере, а не к ответу. Сервер может логировать запросы или возвращать разные метаданные (например, дату последнего изменения), но сам целевой ресурс должен оставаться в том же состоянии.