Что делает HTTP-метод DELETE в RESTful API?

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

Ответ

Метод DELETE — это один из стандартных HTTP-методов, используемых в RESTful API для удаления ресурса, идентифицированного URI (Uniform Resource Identifier). Его ключевые характеристики — идемпотентность и отсутствие тела запроса.

  • Идемпотентность: Многократное выполнение одного и того же DELETE-запроса к одному и тому же ресурсу должно приводить к одному и тому же результату. После первого успешного удаления ресурс исчезает, и последующие запросы должны возвращать статус 404 Not Found или 410 Gone, но не вызывать ошибку сервера.
  • Без тела: Спецификация HTTP не запрещает тело в DELETE-запросе, но обычно оно не используется. Логика удаления должна определяться исключительно URI. Если нужны сложные условия, это часто указывает на дизайн RPC, а не REST.

Типичные коды ответов:

  • 204 No Content: Успешное удаление. Тело ответа отсутствует — это наиболее чистый и распространённый вариант.
  • 200 OK: Удаление прошло успешно, и сервер возвращает в теле ответа статус удалённого ресурса или дополнительную информацию (менее RESTful).
  • 202 Accepted: Запрос на удаление принят, но ещё не обработан (асинхронная операция).
  • 404 Not Found: Ресурс не найден по указанному URI (может считаться успехом с точки зрения идемпотентности, если ресурс уже был удалён).
  • 409 Conflict: Текущее состояние ресурса не позволяет выполнить удаление (например, есть зависимые сущности).

Пример использования с curl и в коде (JavaScript/fetch):

# Удаление пользователя с ID 123
curl -X DELETE https://api.example.com/v1/users/123 
     -H "Authorization: Bearer <token>"
// Удаление ресурса из клиентского JavaScript
async function deletePost(postId) {
    try {
        const response = await fetch(`/api/posts/${postId}`, {
            method: 'DELETE',
            headers: { 'Authorization': `Bearer ${token}` }
        });

        if (response.status === 204) {
            console.log('Post deleted successfully.');
            // Обновить UI: удалить элемент из списка
        } else if (response.status === 404) {
            console.log('Post already deleted or not found.');
        } else {
            console.error('Failed to delete post:', response.status);
        }
    } catch (error) {
        console.error('Network error:', error);
    }
}

Важное замечание по дизайну API: DELETE должен удалять именно тот ресурс, на который указывает URI. Удаление связанных ресурсов (каскадное удаление) должно быть явно документировано в контракте API, так как это может быть неочевидно для клиента и нарушать принцип наименьшего удивления.