Веб

Разница между HTTP POST и PUT: когда использовать для создания

Разница между методами HTTP POST и PUT по RFC 7231: семантика, идемпотентность, статусы. Когда использовать POST для создания ресурса в REST API (сервер генерирует URI) и PUT (клиент указывает URI). Лучшие практики и примеры.

1 ответ 76 просмотров

В чем разница между методами HTTP POST и PUT, и когда каждый из них следует использовать для создания ресурса?

Фон:

  • Согласно RFC 2616, § 9.5, POST используется для создания нового ресурса как подчиненного ресурсу, идентифицированному Request‑URI
  • Согласно RFC 2616, § 9.6, PUT используется для создания или замены ресурса по указанному URI

Вопрос:
Какой метод HTTP следует использовать для создания ресурса, или оба должны поддерживаться в проектировании REST API?

Разница между методами HTTP POST и PUT заключается в их семантике: POST предназначен для обработки запроса сервером с генерацией URI для нового ресурса (не идемпотентен), а PUT — для создания или полной замены ресурса по точно указанному клиентом URI (идемпотентен). Для создания ресурса в REST API используйте POST, если URI неизвестен заранее (сервер присваивает ID), и PUT — когда клиент заранее знает путь, но оба метода стоит поддерживать для гибкости. Согласно RFC 7231, POST предпочтительнее для типичного создания в коллекциях, как подчеркивают рекомендации Microsoft и MDN.


Содержание


Разница между POST и PUT по RFC 7231

Представьте: вы строите REST API, и нужно создать пользователя. Какой метод выбрать — POST или PUT? Ответ кроется в стандарте RFC 7231, который обновил устаревший RFC 2616. Там четко разделены роли.

POST (§4.3.3) — это “общая обработка”. Сервер сам решает, что делать: создать ресурс, запустить процесс или даже отправить email. URI запроса обычно указывает коллекцию (/users), а новый ресурс получает свой путь (/users/123), который сервер возвращает в Location. Не идемпотентен: повторный POST может создать дубликат.

PUT (§4.3.4) — точечная операция. Клиент говорит: “Создай или замени именно по этому URI (/users/123)”. Если ресурса нет — создай. Повтор? Ничего не меняется, полная идемпотентность. Тело запроса должно полностью описывать ресурс.

Аспект POST PUT
URI ресурса Коллекция (сервер генерирует) Конкретный (клиент указывает)
Идемпотентность Нет (дубликаты возможны) Да (повторы безопасны)
Статус при создании 201 Created + Location 201 Created (Location опционально)
Тело Частичное/полное (сервер решает) Полное (замена)

Почему это важно? Неправильный выбор ломает клиенты. Браузеры кэшируют GET, но POST/PUT требуют осторожности. В MDN подчеркивают: путайте на свой страх.

А фон из вашего вопроса? RFC 2616 (§9.5/9.6) похож, но 7231 точнее: POST для “подчиненных” ресурсов коллекций, PUT — прямая загрузка по URI.


Семантика POST: когда использовать для создания ресурса

POST — король создания в большинстве API. Почему? Потому что клиент редко знает ID заранее. Отправьте POST /users с JSON {name: “Иван”}, сервер создаст /users/456 и вернет 201 Created, Location: /users/456.

Пример curl:

curl -X POST https://api.example.com/users \
 -H "Content-Type: application/json" \
 -d '{"name": "Иван", "email": "ivan@example.com"}'

Ответ: 201, тело с данными, Location в заголовке. Идеально для коллекций: /posts, /orders.

Но не идемпотентен. Повторите запрос — может родиться второй Иван. Решение? Используйте idempotency-key в заголовке (Stripe так делает). MDN POST рекомендует для форм, коллекций, неатомарных операций.

Когда POST? Всегда для “создай новый, сам придумай ID”. В 90% случаев — ваш выбор.


Семантика PUT: создание по известному URI

PUT реже для чистого создания, но крут, когда URI предопределен. Клиент знает: “Загрузи аватар по /users/123/avatar”. Если нет — создай.

Пример:

curl -X PUT https://api.example.com/users/123 \
 -H "Content-Type: application/json" \
 -d '{"name": "Иван Петров", "age": 30}'

Если /users/123 пуст — 201 Created. Уже есть? 200 OK, полная замена. Идемпотентно: жмите сколько угодно.

MDN PUT предупреждает: тело должно быть полным, иначе данные сотрутся. Не для частичных обновлений (там PATCH).

Когда PUT для создания? Редко: если ID из внешнего источника (UUID от клиента) или загрузка файлов по фиксированному пути. В Baeldung примеры показывают: PUT /articles/my-known-slug.

Но осторожно: клиенты не всегда знают URI. Поэтому не основной метод.


POST vs PUT в REST API: лучшие практики

В REST нет строгого “только POST”. Roy Fielding (отец REST) в StackOverflow советует POST для создания. Microsoft в API design то же: POST /customers, сервер дает ID.

Практика:

  • POST /users → создай, получи /users/{id}.
  • PUT /users/{id} → замени/создай по ID.

Из Postman блога: правило большого пальца — POST, если сервер решает URI. Restfulapi.net добавляет: POST для детей коллекций.

Таблица best practices:

Сценарий POST PUT
Новый пользователь в /users Да Нет (ID неизвестен)
Обновить/создать /users/known-uuid Нет Да
Загрузка файла /files/fixed-name Нет Да

GitHub, Twitter API — POST для твитов/репозиториев. Почему? Масштаб, безопасность.


Идемпотентность, статусы ответов и безопасность

Идемпотентность — ключ. PUT: повторите — то же. POST: может удвоить заказы. Решение: ключи вроде X-Idempotency-Key.

Статусы:

  • Создание: 201 Created (оба).
  • Уже есть (PUT): 200/204 OK.
  • Конфликт: 409 (дубликат email).

Безопасность: PUT раскрывает URI, уязвим к угадыванию (/users/1). POST прячет. TheServerSide отмечает: PUT для trusted клиентов.

Тестируйте в Postman: повторите PUT — мирно, POST — хаос без ключей.

Что если трафик? Идемпотентные PUT проще для retry в сетях.


Должны ли API поддерживать оба метода для создания?

Да, поддерживайте оба. Зачем? Гибкость. Большинство — POST /resource. Но для миграций или клиентов с UUID — PUT /{id}.

StackOverflow Blog: POST для append, PUT для set. Stripe, AWS — оба есть.

Минусы двойной поддержки? Документация. Swagger: опишите четко.

В итоге: базовый API — POST. Продвинутый — +PUT. Клиенты спасибо скажут.


Источники

  1. RFC 7231 — Стандарт семантики HTTP/1.1, разница POST/PUT: https://datatracker.ietf.org/doc/html/rfc7231
  2. MDN Web Docs: POST — Описание семантики POST для создания и коллекций: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/POST
  3. MDN Web Docs: PUT — Детали идемпотентности PUT и статусов создания: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/PUT
  4. Microsoft API Design Best Practices — Рекомендации POST для создания в REST: https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design
  5. Baeldung: PUT vs POST — Сравнение с примерами кода и статусами: https://www.baeldung.com/rest-http-put-vs-post
  6. Stack Overflow: POST vs PUT — Обсуждение от Roy Fielding, практика REST: https://stackoverflow.com/questions/630453/what-is-the-difference-between-post-and-put-in-http
  7. Postman Blog: PUT vs POST — Правила выбора для API-дизайна: https://blog.postman.com/put-vs-post/

Заключение

Разница POST и PUT проста, но критична: POST для сервер-генерируемого URI при создании ресурса (основной в REST API), PUT — для клиентского URI с идемпотентностью. Поддерживайте оба для полного покрытия сценариев, следуя RFC 7231 и best practices от Microsoft/MDN. Начните с POST — и ваш API станет надежным, масштабируемым. Экспериментируйте в sandbox, увидите разницу на деле.

Авторы
Проверено модерацией
Модерация
Разница между HTTP POST и PUT: когда использовать для создания