Веб

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

Разница между HTTP методами POST и PUT по RFC 9110: семантика, идемпотентность, статус-коды. Когда использовать POST для коллекций и PUT для известных URI в REST API. Best practices проектирования с примерами curl.

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 (сервер генерирует финальный URI в Location), не идемпотентен и подходит для коллекций вроде /users. PUT же создаёт или полностью заменяет ресурс точно по клиентскому URI, строго идемпотентен и идеален, когда URI известен заранее, например /users/123. В проектировании REST API оба метода стоит поддерживать — POST для большинства случаев создания (стандарт ~90%), PUT для предсказуемых URI с повторной безопасностью.


Содержание


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

Представьте: клиент шлёт запрос на сервер. Что дальше? Всё зависит от семантики, закреплённой в RFC 9110 — это актуальный стандарт после RFC 2616. POST (§9.3.3) не просто “отправка данных”: он запрашивает обработку (часто создание подчинённого ресурса), где Request-URI — это коллекция или обработчик, а сервер сам решает URI для новичка и возвращает его в Location. Не идемпотентен: повтор вызовет дубли (новые ресурсы).

PUT (§9.3.4) — полная противоположность. Клиент точно знает URI ресурса и говорит: “Создай или замени именно здесь”. Сервер обязан выполнить атомарно: если ресурса нет — создай (201 Created), если есть — замени целиком (200 OK или 204 No Content). Идемпотентность на первом месте: сколько ни повторяй, результат один.

Аспект POST PUT
URI в запросе Коллекция/обработчик (сервер генерирует URI) Точный ресурс (клиент задаёт URI)
Семантика Запрос на обработку/создание подчинённого Создание или замена по URI
Идемпотентность Нет (дубли возможны) Да (повторы безопасны)
Тело запроса Любое (JSON, форма, файл) Полное представление ресурса

Почему это важно? Без понимания разницы POST PUT ваш API превратится в спагетти: клиенты будут путаться, а retry-логика сломается. RFC подчёркивает: POST для расширений (БД вставка), PUT — для чистого CRUD.


Когда использовать POST для создания ресурса

POST — король создания в 90% случаев. Почему? Клиент редко знает URI заранее. Представьте /api/users: шлёшь данные юзера, сервер создаёт /api/users/456 и кидает 201 Created с Location: /api/users/456. Просто, гибко.

Сценарии:

  • Коллекции: POST /posts — новый пост в блоге.
  • Подчинённые ресурсы: POST /orders/123/items — товар в заказ.
  • Расширения: Загрузка файла, обработка формы (не чистый ресурс).

Пример curl:

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

Ответ: 201 Created, Location: /users/789. Повторишь? Получишь второго Ивана — вот цена неидемпотентности. Но MDN по POST подтверждает: это норма для новых сущностей.

А если дубли не нужны? Добавьте Idempotency-Key в хедер — современный хак для безопасности.


Когда использовать PUT для создания ресурса

PUT сияет, когда URI предопределён. Клиент говорит: “Я знаю, куда класть — /users/uuid-123”. Сервер создаёт, если пусто, или перезаписывает. Идеально для:

  • Клиент-генерируемых ID: UUID в URI (/documents/550e8400).
  • Замены: Часто PUT = update, но RFC позволяет create.

Пример:

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

Ответ: 201 (новый) или 200/204 (существующий). Повтори — ничего не сломается! MDN по PUT отмечает: тело должно быть полным представлением, частичные изменения — PATCH.

Но осторожно: если /users/123 занято — 409 Conflict. PUT не для коллекций — зачем клиенту гадать свободный ID?


POST vs PUT в REST API: идемпотентность и статус-коды

Вот где разница POST PUT бьёт ключом. Идемпотентность: PUT — да (N запросов = 1 эффект), POST — нет (N = N ресурсов). Retry после таймаута? PUT безопасен, POST рискует дублями.

Статусы:

Метод Создание (новый) Обновление (существующий) Конфликт
POST 201 Created (Location) 200/201 (зависит от логики) 409/422
PUT 201 Created 200 OK / 204 No Content 409 Conflict

Из Baeldung: POST для серверного ID, PUT для клиентского. Postman блог добавляет: правило “POST — сервер URI, PUT — клиент URI”.

В реальности? Клиенты (Postman, curl) ожидают предсказуемости. Без идемпотентности микросервисы взорвутся на сетевых сбоях.


Best practices проектирования REST API

Поддерживайте оба — это консенсус. Microsoft API design советует: POST /orders для коллекций, PUT /articles/uuid для известных. Roy Fielding (REST автор) на StackOverflow: “Prefer POST, PUT только если URI known”.

Правила:

  1. POST /resources — стандарт для create.
  2. PUT /resources/{id} — create/update, если ID от клиента (UUID).
  3. Всегда Location в 201.
  4. Идемпотентность: Key для POST, native для PUT.
  5. Документируйте в OpenAPI.

Из restfulapi.net: в 95% API POST доминирует, PUT — ниша. Но гибкость окупается: клиенты счастливы, масштабируемость на уровне.

Ошибки новичков? PUT без 409 — перезапись чужого! POST без Location — слепой полёт.


Источники

  1. RFC 9110 — Официальный стандарт HTTP семантики POST и PUT: https://httpwg.org/specs/rfc9110.html
  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. RESTful API: PUT vs POST — Сравнение для REST, рекомендации по URI: https://restfulapi.net/rest-put-vs-post/
  5. Microsoft Azure API Design — Best practices для POST/PUT в коллекциях: https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design
  6. Stack Overflow: POST vs PUT — Обсуждение с ссылкой на Fielding: https://stackoverflow.com/questions/630453/what-is-the-difference-between-post-and-put-in-http
  7. Baeldung: REST PUT vs POST — Практические примеры и статусы: https://www.baeldung.com/rest-http-put-vs-post

Заключение

Разница POST vs PUT — в контроле URI и идемпотентности: POST для серверных ID и коллекций (основной выбор для создания), PUT для клиентских URI с безопасными повторами. В REST API проектируйте оба — это обеспечит гибкость, как рекомендуют RFC, MDN и Microsoft. Начните с POST, добавьте PUT для продвинутых сценариев, и ваши клиенты скажут спасибо. Вопросы? Тестируйте в Postman!

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