Веб

POST vs PUT в REST API: разница и использование

Узнайте разницу между POST и PUT в REST API для создания ресурсов. Когда использовать каждый метод и почему идемпотентность важна.

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

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

Фон:

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

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

В REST API методы POST и PUT различаются семантикой: POST подходит для создания нового ресурса в коллекции, где сервер сам генерирует URI и возвращает 201 Created с Location. PUT, напротив, используется клиентом для создания или полной замены ресурса по заранее известному URI — он идемпотентен, то есть повторные запросы не меняют результат. В проектировании REST API лучше поддерживать оба метода: POST для типичных сценариев новых записей, PUT — когда ID ресурса известен заранее, чтобы обеспечить гибкость и соответствие HTTP-стандартам.


Содержание


Что такое методы REST API: POST и PUT

Представьте: вы строите API для управления пользователями. Клиент шлет данные — имя, email. Какой метод HTTP выбрать для записи в базу? Методы REST API вроде POST и PUT кажутся похожими, но их разница коренится в HTTP-семантике.

POST — это универсальный инструмент для отправки данных на сервер. Он не обещает идемпотентности: один запрос создаст ресурс, повторный может дублировать его. Сервер решает, куда положить новый объект, часто в коллекцию вроде /users. Получаете 201 Created и ссылку в заголовке Location.

PUT, в свою очередь, строже. Клиент сам указывает полный путь: /users/123. Если ресурса нет — создаст, если есть — заменит целиком. Повторите запрос хоть сто раз — ничего не изменится. Идеально для сценариев, где ID предопределен.

А HTTP GET POST PUT DELETE — это базовый арсенал CRUD в REST. Но путают именно при создании. Почему? Потому что оба возвращают 201, но логика разная. Давайте разберем по стандартам.

Вот таблица для ясности:

Аспект POST PUT
URI Коллекция (/users) Конкретный ресурс (/users/123)
Идемпотентность Нет (может дублировать) Да (повторы безопасны)
Статус успеха 201 Created 201 Created или 200 OK
Пример Создать юзера без ID Создать/обновить по ID

Данные из RFC 7231, где обновили старый RFC 2616.


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

Стандарты не шутят. В RFC 7231 §4.3.3 POST описан как запрос для обработки данных: сервер может создать подчиненный ресурс. Request-URI — это “куда отправить”, не обязательно конечный путь объекта. Классика: форма логина или фото в соцсеть.

А §4.3.4 для PUT: “Заменить целевой ресурс указанным состоянием”. Если ресурса нет — создайте. URI фиксирован клиентом. Это ключ к PUT vs POST: первый — “сделай что-то с данными”, второй — “положи именно сюда”.

Обновление от RFC 2616: там §9.5/9.6 говорили похожим языком, но 7231 уточнило нюансы безопасности и кэширования. На Stack Overflow топ-ответы ссылаются именно на это — тысячи разработчиков спорили годами.

Но практика? HTTP POST PUT часто игнорируют. Клиенты дублируют POST — база растет мусором. PUT спасает: повторил — и ладно. Вопрос: а если ID генерирует клиент? Тогда PUT в самый раз.

Коротко: POST — серверный контроль, PUT — клиентский.


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

Метод HTTP для создания нового ресурса — чаще POST, особенно в коллекциях. Зачем? Сервер генерирует уникальный ID (UUID или автоинкремент). Клиент не знает заранее, куда класть.

Пример: API пользователей. Запрос:

POST /api/users
Content-Type: application/json

{
 "name": "Иван",
 "email": "ivan@example.com"
}

Ответ:

201 Created
Location: /api/users/456

Сервер выбрал ID 456. Повторите — может создать 457, если нет дедупликации. Идеально для неидемпотентных методов REST API, где дубли возможны (но с 409 Conflict при совпадении email).

По restfulapi.net, POST — норма для новых записей в REST. Когда еще? Загрузка файлов, сложные формы. Клиент расслаблен: шлет на /posts, сервер сам разберется.

Но минус: нет гарантии повторов. Если сеть глючит, клиент не знает — создал или нет. Поэтому 202 Accepted иногда юзают.

В общем, POST — для “дай мне новый слот”.


Когда использовать PUT в REST API

Теперь REST API PUT метод. Когда клиент знает URI заранее? Например, API с предопределенными ID (по внешнему ключу, как /invoices/INV-2026-001). Или миграции данных.

Пример curl:

PUT /api/users/123
Content-Type: application/json

{
 "name": "Иван Иванов",
 "email": "ivan@example.com"
}

Если 123 пуст — создаст (201). Есть — заменит (200/204). Повторите — тот же результат. Идемпотентные методы HTTP в деле!

По KeyCDN, PUT для случаев, где URI статичен: обновление профиля по ID из JWT. Плюс: клиенты любят — можно ретраить без риска.

Минус? Полная замена: пропустили поле — оно обнулится. Для частичных патчей — PATCH.

Когда PUT vs POST? PUT, если ID от клиента (UUID в payload).


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

Какие методы HTTP идемпотентные? GET, PUT, DELETE, HEAD — да. POST, PATCH — нет. Идемпотентность значит: N запросов = 1 результат. Критично для сетей — ретраи без дублей.

Почему POST неидепотентен? Сервер может создать несколько. В RFC 7231 прямо: клиенты не должны предполагать безопасность повторов для POST.

Пример беды: оплата заказа POST /payments. Сеть обрывается, клиент ретраит — два платежа. PUT /payments/ord-123 спасет.

В API и REST методы и смысл CRUD: Create — POST (коллекция), но PUT для точного. На api-fiddle советуют: POST для /todos, PUT для /todos/my-uuid.

Тестируйте! Postman с ретраями покажет разницу. Без идемпотентности — хаос в проде.


Лучшие практики: поддерживать оба метода в REST API

HTTP методы GET POST PUT DELETE — все в API. Поддерживать оба для создания? Да! Гибкость рулит.

  • POST /users — новый юзер, сервер ID.
  • PUT /users/{id} — создать/обновить по известному ID.

Статусы: POST всегда 201 + Location. PUT: 201/200/204/409 (конфликт).

Из restfulapi.net: 90% API так делают. Stripe, GitHub — примеры.

Советы:

  1. Документируйте в OpenAPI.
  2. Валидация ID в PUT (UUID?).
  3. Логируйте повторы.
  4. Для коллекций — POST only.

Вопрос: а если один? POST хватит для 80%, но PUT добавит polish. В вашем API — решайте по use-case.


Источники

  1. HTTP/1.1 Semantics and Content — Стандарт IETF по семантике методов POST и PUT, включая идемпотентность: https://datatracker.ietf.org/doc/html/rfc7231
  2. REST API PUT vs POST — Подробное сравнение методов для создания ресурсов в RESTful API: https://restfulapi.net/rest-put-vs-post/
  3. PUT vs POST — Рекомендации по использованию в веб-API с примерами статус-кодов: https://www.keycdn.com/support/put-vs-post
  4. PUT vs POST for RESTful resource creation — Практические кейсы создания ресурсов с учетом URI: https://blog.api-fiddle.com/posts/put-vs-post-for-restful-resource-creation
  5. What is the difference between POST and PUT in HTTP — Обсуждение различий с ссылками на RFC: https://stackoverflow.com/questions/630453/what-is-the-difference-between-post-and-put-in-http

Заключение

В REST API методы POST и PUT дополняют друг друга: POST для серверного создания в коллекциях, PUT для клиентского URI и идемпотентности. Поддерживайте оба — это стандарт лучших практик, снижает ошибки и упрощает клиентов. Выберите по сценарию: не знаете ID — POST, знаете — PUT. Протестируйте на своем проекте, и API засияет.

Авторы
Проверено модерацией
Модерация