НейроАгент

PUT vs POST: Руководство по созданию REST API

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

Вопрос

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

Фон:

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

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

НейроАгент

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

Содержание

Ключевые различия между POST и PUT

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

Метод POST:

  • Определен в RFC 2616 §9.5 как “используется для создания нового ресурса как подчиненного ресурса, идентифицированного Request-URI”
  • Сервер определяет URI нового созданного ресурса
  • Обычно возвращает HTTP 201 (Created) с заголовком Location, указывающим на новый ресурс
  • Неидемпотентен — повторные идентичные запросы могут создавать несколько ресурсов
  • Используется для действий, не имеющих определенного сопоставления URI

Метод PUT:

  • Определен в RFC 2616 §9.6 как “используется для создания или замены ресурса по указанному URI”
  • Клиент указывает точный URI для ресурса, который создается или обновляется
  • Обычно возвращает HTTP 200 (OK) или HTTP 204 (No Content) при успешных обновлениях
  • Идемпотентен — повторные идентичные запросы имеют тот же эффект, что и один запрос
  • Используется, когда клиент полностью знает идентификатор ресурса

Ключевое различие: POST создает ресурсы под контролем сервера, в то время как PUT создает или заменяет ресурсы в местоположениях, указанных клиентом. Это влияет как на процесс присвоения URI, так и на гарантии идемпотентности.

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

POST является предпочтительным методом в следующих сценариях:

Создание дочерних ресурсов:

  • При добавлении нового ресурса в коллекцию
  • Пример: POST /articles создает новую статью в коллекции статей
  • Сервер назначает URI нового ресурса (например, /articles/123)

Неизвестные URI ресурсов:

  • Когда клиент не знает точный URI создаваемого ресурса
  • Когда ресурсы имеют идентификаторы, сгенерированные сервером
  • Когда ресурс подчинен другому ресурсу

Не-CRUD операции:

  • Для действий, не вписывающихся в традиционные CRUD операции
  • Для обработки форм или запуска операций
  • Для пакетных операций или сложных рабочих процессов

Согласно лучшим практикам проектирования API от Microsoft, “POST-запросы используются для добавления нового ресурса в коллекцию, идентифицированную URI”. Это соответствует принципу RESTful, где POST работает с коллекциями, а не с конкретными ресурсами.

Пример: Создание новой учетной записи пользователя, где идентификатор пользователя генерируется автоматически сервером:

http
POST /users
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com"
}

HTTP/1.1 201 Created
Location: /users/12345

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

PUT становится подходящим в следующих ситуациях:

URI ресурсов, указанные клиентом:

  • Когда клиент знает точный URI создаваемого ресурса
  • При использовании UUID или других идентификаторов, контролируемых клиентом
  • При реализации оптимистичного контроля параллелизма

Идемпотентное создание ресурсов:

  • Когда нужно гарантировать, что попытки дублирования создания не создают несколько ресурсов
  • Когда один и тот же запрос можно безопасно повторить
  • При реализации логики повторных попыток для надежных приложений

Полная замена ресурса:

  • При создании или полной замене ресурса по конкретному URI
  • При использовании PUT как для операций создания, так и обновления

Как объясняется на Baeldung, “используйте метод PUT для создания нового ресурса, а метод POST для обновления существующего ресурса” — это распространенный шаблон, хотя он может варьироваться в зависимости от решений по проектированию API.

Пример: Создание пользователя с UUID, указанным клиентом:

http
PUT /users/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com"
}

HTTP/1.1 201 Created

Рассмотрения идемпотентности

Идемпотентность является ключевым фактором при выборе между POST и PUT:

Идемпотентность PUT:

  • PUT является идемпотентным по спецификации HTTP
  • Несколько идентичных запросов PUT дают тот же результат, что и один запрос
  • Делает PUT безопасным для повторных попыток без побочных эффектов
  • Критически важно для надежных распределенных систем

Неидемпотентность POST:

  • POST по умолчанию не является идемпотентным
  • Несколько идентичных запросов POST могут создавать несколько ресурсов
  • Требует дополнительной серверной логики для предотвращения дублирования созданий
  • Может потребовать пользовательских ключей идемпотентности или дедупликации запросов

Согласно RFC 7231, “метод запроса считается ‘идемпотентным’, если предполагаемый эффект на сервере от нескольких идентичных запросов с этим методом такой же, как эффект от одного такого запроса”. Методы GET, HEAD, PUT и DELETE обладают этим свойством.

Практические последствия:

  • Сбои сети: PUT можно безопасно повторить; POST нельзя
  • Повторные попытки клиента: PUT не вызовет дублирования ресурсов; POST может
  • Контроль параллелизма: PUT хорошо работает с оптимистичной блокировкой

Лучшие практики проектирования REST API

При проектировании REST API учитывайте эти лучшие практики:

Последовательные шаблоны URI:

  • POST /resources для создания ресурсов в коллекциях
  • PUT /resources/{id} для создания или обновления конкретных ресурсов
  • Используйте четкие, иерархические структуры URI

Выбор кодов состояния:

  • Успешное создание POST: HTTP 201 (Created)
  • Создание/обновление PUT: HTTP 200 (OK) или HTTP 204 (No Content)
  • Включайте заголовок Location для ресурсов, созданных через POST

Семантика методов:

  • Следуйте принципам REST и семантике HTTP
  • Используйте POST для действий, создающих ресурсы без указания URI
  • Используйте PUT для операций, нацеленных на конкретные URI ресурсов

Лучшие практики проектирования API от Stack Overflow рекомендуют: “POST /articles/ предназначен для добавления новой статьи, PUT /articles/:id — для обновления статьи с заданным идентификатором.”

Рассмотрения со стороны клиента:

  • Четко документируйте шаблоны URI для потребителей API
  • Предоставляйте четкие сообщения об ошибках для недопустимых URI ресурсов
  • Рассмотрите возможность поддержки обоих методов, когда это уместно

Альтернативные подходы

Хотя традиционные шаблоны хорошо установлены, некоторые современные API используют альтернативные подходы:

POST для создания и обновления:

  • Некоторые API используют исключительно POST как для создания, так и для обновления
  • Это упрощает проектирование API, но может строго не следовать принципам REST
  • Распространено в архитектурах микросервисов

PUT только для создания:

  • Некоторые API ограничивают PUT только созданием ресурсов
  • Обновления обрабатываются через PATCH или другие методы
  • Этот подход подчеркивает идемпотентность для создания ресурсов

Гибридные подходы:

  • Используйте POST для неизвестных URI и PUT для известных URI
  • Реализуйте пользовательские механизмы идемпотентности для POST-запросов
  • Предоставляйте оба метода, когда случай использования поддерживает оба

Как отмечено в RESTful cookbook, “возможно, допустимо и даже предпочтительно в некоторых случаях использовать PUT для создания ресурсов или POST для обновления ресурсов.”

Заключение

Выбор между POST и PUT для создания ресурсов зависит от нескольких факторов:

  1. Контроль URI ресурса: Используйте POST, когда сервер назначает URI ресурса, и PUT, когда клиент его указывает
  2. Требования идемпотентности: Выбирайте PUT, когда вам нужна идемпотентность для безопасных повторных попыток
  3. Коллекции против отдельных ресурсов: Используйте POST для добавления в коллекции и PUT для нацеливания на конкретные ресурсы
  4. Последовательность API: Поддерживайте последовательные шаблоны во всем вашем проектировании API

На практике многие REST API поддерживают оба метода там, где это уместно — POST для общего создания ресурсов в коллекциях и PUT для создания ресурсов, когда клиент знает идентификатор. Это обеспечивает гибкость для разных случаев использования при сохранении принципов RESTful.

Для большинства приложений рекомендуется начинать с традиционного шаблона (POST для создания, PUT для обновлений), но будьте готовы адаптироваться в зависимости от ваших конкретных требований и потребностей потребителей вашего API.

Источники

  1. Stack Overflow - What is the difference between POST and PUT in HTTP?
  2. RESTful API - Difference between PUT and POST in REST API
  3. The Server Side - PUT vs POST: What’s the difference?
  4. Stack Overflow Blog - Best practices for REST API design
  5. Microsoft Learn - Web API Design Best Practices
  6. Baeldung - HTTP PUT vs. POST in REST API
  7. The RESTful Cookbook - When to use PUT or POST
  8. RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
  9. W3C - HTTP/1.1: Method Definitions
  10. MScharhag - HTTP methods: Idempotency and Safety