Веб

Разница POST и PUT в REST API: когда использовать

Разница между HTTP POST и PUT по RFC 2616: POST для создания подчиненного ресурса в коллекции (сервер генерирует URI), PUT — идемпотентная замена или создание по точному пути. Рекомендации по дизайну REST API с примерами и статусами.

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

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

Фон:

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

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

Разница между методами HTTP POST и PUT проста, но критична для REST API: POST создает новый подчиненный ресурс по URI обработчика (сервер генерирует ID и возвращает Location), а PUT размещает или заменяет ресурс точно по указанному URI, оставаясь идемпотентным. Для создания ресурса без известного URI используйте POST — это стандарт по RFC 2616 (§9.5), а PUT подойдет, если клиент заранее знает путь, как рекомендует Roy Fielding. В дизайне REST API лучше поддерживать оба метода для гибкости: POST для коллекций, PUT для upsert-операций.


Содержание


Что такое HTTP POST и когда его использовать

POST — это универсальный метод для отправки данных на сервер, но в контексте REST он идеален для создания новых ресурсов. Представьте: у вас есть эндпоинт /api/users — коллекция пользователей. Клиент шлет POST-запрос с JSON-телом { "name": "Иван", "email": "ivan@example.com" }. Сервер создает пользователя, присваивает ему уникальный ID (скажем, 123) и отвечает статусом 201 Created с заголовком Location: /api/users/123. Почему так? Потому что по RFC 2616 (§9.5) POST работает с подчиненным ресурсом: URI запроса — это обработчик (коллекция), а не точный путь будущего объекта.

Это удобно, когда клиент не знает ID заранее. Повторите запрос — и вуаля, дубликат. POST не идемпотентен, но это нормально для создания. А если сервер перегружен? Возвращает 429 Too Many Requests или 503. В реальности Postman подчеркивает: POST для новых сущностей, где сервер решает URI.

Пример curl:

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

Ответ: HTTP/1.1 201 Created + Location.

Но подождите, а если нужно создать с предопределенным ID? Тут POST тоже сработает, но это не RESTful — лучше перейти к PUT.


Что такое HTTP PUT и его особенности

PUT — метод для точного размещения ресурса. Укажите полный URI, например /api/users/123, и сервер либо создаст ресурс там (если пусто), либо полностью заменит существующий. По RFC 2616 (§9.6) это атомарная операция: клиент знает URI заранее, шлет данные, и сервер обязан их сохранить именно туда. Идемпотентность на первом месте — повторите запрос 10 раз, результат один и тот же.

Статусы? 201 Created для нового, 200 OK или 204 No Content для замены, 409 Conflict если URI занят конфликтующим ресурсом. MDN для PUT уточняет: это не частичное обновление (для него PATCH), а полная замена.

Пример:

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

Если /users/123 не существовало — создано. Повторите — ничего не меняется. Идеально для миграций или когда клиент генерирует UUID заранее.

Но PUT требует знания URI. Если ID генерирует сервер — не ваш выбор.


Различия между POST и PUT по RFC 2616

RFC 2616 четко разграничивает: POST (§9.5) — для запросов, где URI это обработчик, результат может быть чем угодно (создание подчиненного ресурса, обработка формы). PUT (§9.6) — строго для ресурса по URI, с гарантией замены или создания.

Вот таблица сравнения из restfulapi.net:

Аспект POST PUT
Семантика Создание подчиненного ресурса Создание/замена по точному URI
URI Обработчик (e.g. /users) Точный ресурс (e.g. /users/123)
Идемпотентность Нет (дубли при повторe) Да (повтор = тот же результат)
Статус при создании 201 + Location 201 Created или 200/204
Тело Любое Полное представление ресурса

Цитата из RFC для POST: “The request body is used to submit new data to the resource identified by the Request-URI”. Для PUT: “Replaces all current representations of the target resource”.

В KeyCDN добавляют: POST шире — для триггеров действий, PUT — чисто CRUD.

Разница не в “создать vs обновить”, а в контроле URI и безопасности повторных вызовов.


POST vs PUT для создания ресурсов в REST API

Для чистого создания ресурса? POST — ваш основной выбор. Почему? Клиент шлет на коллекцию /posts, сервер создает /posts/456 и возвращает ссылку. Это следует Fielding’у: в Stack Overflow он пишет, что PUT когда “клиент знает URI заранее”.

PUT для создания — редкость, но полезна: клиент генерирует ID (UUID), PUT /posts/abc-uuid-123. Если ресурс есть — upsert (update or insert). Baeldung приводит пример: в GitHub API PUT иногда upsert’ит.

А если оба? Поддерживайте! POST для “создай новый в коллекции”, PUT для “положи сюда”. REST Cookbook советует: коллекции — POST, известные пути — PUT.

Вопрос: а если клиент ошибся URI в PUT? 404 или 409. В POST — сервер спасет.


Идемпотентность: почему это важно

Идемпотентность — ключ. PUT: повторите 100 раз — один ресурс. POST: 100 дублей. Почему важно? Сети ненадежны. Таймаут? Клиент retransmit’нет. Для PUT — безопасно. POST — проверяйте сервером (e.g. unique email).

Пример из MDN POST: “Repeated identical POST may create multiple resources”. PUT нет.

В API добавляйте Idempotency-Key заголовок для POST, чтобы эмулировать. Но по умолчанию — PUT выигрывает в надежности.

Представьте заказ в e-commerce: POST /orders — новый заказ при сбое. PUT /orders/123 — безопасно обновит.


Рекомендации по дизайну REST API

В современном REST (RFC 7231 обновил 2616) оба метода обязательны. Стандарт:

  • POST для создания без ID: /api/items → 201 Location.
  • PUT для создания/замены с ID: /api/items/{id} → 201/200/204.
  • Избегайте PUT без аутентификации — любой перезапишет.
  • Всегда возвращайте Location в 201.

Software Engineering SE подтверждает: по Fielding, POST primary для создания. Но гибкость — король.

Тестируйте Postman: оба метода ускорят dev.


Источники

  1. What is the difference between POST and PUT in HTTP? — Объяснение различий от Roy Fielding и примеры: https://stackoverflow.com/questions/630453/what-is-the-difference-between-post-and-put-in-http
  2. PUT vs. POST: What’s the Difference? — Сравнение для создания ресурсов в API: https://blog.postman.com/put-vs-post/
  3. REST – Put vs Post — Детальный разбор по RFC 2616 с таблицами: https://restfulapi.net/rest-put-vs-post/
  4. PUT vs POST in REST API — Фокус на идемпотентности и статусах: https://www.baeldung.com/rest-http-put-vs-post
  5. PUT — Официальная документация MDN по PUT и статусам: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/PUT
  6. POST — Официальная документация MDN по POST и семантике: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/POST
  7. PUT vs POST — Рекомендации по URI и идемпотентности: https://www.keycdn.com/support/put-vs-post
  8. PUT vs POST — Практические советы по REST Cookbook: https://restcookbook.com/HTTP Methods/put-vs-post/

Заключение

Разница POST и PUT в REST API — в URI-контроле и идемпотентности: POST для новых ресурсов в коллекциях (сервер генерирует путь), PUT для точного размещения или замены. Используйте POST по умолчанию для создания, PUT когда ID известен — и обязательно поддерживайте оба для robust дизайна. Это сэкономит нервы при сетевых сбоях и сделает API по-настоящему RESTful.

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