RESTful способ создания нескольких элементов в одном запросе

Я работаю над небольшой клиент-серверной программой для сбора заказов. Я хочу сделать это "REST (полностью) способом".

Что я хочу сделать:

Соберите все строки заказа (продукт и количество) и отправьте полный заказ на сервер

На данный момент я вижу два варианта сделать это:

  1. Отправьте каждую строку заказа на сервер: POST qty и product_id

На самом деле я не хочу этого делать, потому что хочу ограничить количество запросов к серверу, поэтому вариант 2:

  1. Соберите все строки заказов и сразу отправьте их на сервер.

Как реализовать вариант 2? у меня есть пара идей: Оберните все строки заказа в объект JSON и отправьте его на сервер или используйте массив для публикации строк заказа.

Является ли реализация варианта 2 хорошей идеей или хорошей практикой, и если да, то как мне это сделать.

Что такое хорошая практика?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
126
0
84 572
7

Ответы 7

Вы не захотите отправлять заголовки HTTP для 100 строк заказа. Вы также не хотите создавать больше запросов, чем необходимо.

Отправьте весь заказ в одном объекте JSON на сервер: server / order или server / order / new. Вернуть что-то, что указывает на: server / order / order_id

Также рассмотрите возможность использования СОЗДАЙТЕ PUT вместо POST

Я полагаю, это метод HTTP POST. Не существует такой вещи, как метод CREATE HTTP.

Milan Novota 04.01.2009 23:27

Нет? Ой, подождите, не было. Вместо этого были PUT.

Cheery 05.01.2009 01:00

Зачем вам использовать PUT для создания контента? Именно для этого и предназначен метод HTTP POST.

thecoshman 27.06.2013 19:14

Вы используете PUT для создания ресурсов, когда хотите, чтобы клиент указывал URI ресурса, как в webdav. Я не согласен с использованием плаката PUT, но он имеет место при создании ресурсов, хотя это место может быть ограничено по объему.

user602525 12.01.2015 22:25

@thecoshman, я думаю, он имеет в виду, что он изменяет коллекцию через PUT, но это должно заменить все ресурсы (а не добавлять ресурсы). Таким образом, используя ту же логику, мы должны вместо этого использовать PATCH, учитывая, что мы частично изменяем коллекцию, добавляя новые ресурсы.

MhdSyrwan 15.04.2015 15:58

@MhdSyrwan Нет, это совершенно новый порядок, нет существующего порядка для «PATCH», поэтому следует использовать либо PUT, либо POST. В этом случае ваш URL-адрес будет похож на /orders, вам все равно, какой URL-адрес назначен каждому отдельному заказу, поэтому POST будет выбором. Теперь, возможно, да, он модифицирует всю коллекцию заказов, однако «заказы» - это не единственный ресурс, и по этой логике можно утверждать, что все является частью корневого ресурса.

thecoshman 17.04.2015 10:32

Примечание: POST-запрос объекта должен привести к тому, что объект станет подчиненным по отношению к ресурсу, указанному в запросе, и не будет идемпотентным. PUT заменяет объект по адресу и является идемпотентным. Идемпотентность (слово?) - важное ожидание потребителей.

Luke Puplett 05.01.2016 17:22

Ваша идея кажется мне верной. Реализация - дело ваших предпочтений. Вы можете использовать JSON или просто параметры для этого (массив "order_lines []") и сделать

POST /orders

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

Хотя массовые операции (например, пакетное создание) необходимы во многих системах, они формально не рассматриваются в архитектурном стиле RESTful.

Я обнаружил, что POSTing коллекции, как вы предложили, в основном работает, но проблемы возникают, когда вам нужно сообщить об ошибках в ответ на такой запрос. Такие проблемы усугубляются, когда происходит несколько сбоев по разным причинам или когда сервер не поддерживает транзакции. Я предлагаю вам, если нет проблем с производительностью, например, когда поставщик услуг находится в локальной сети (не в глобальной сети) или данные относительно малы, стоит отправить 100 запросов POST на сервер. Будьте проще, начните с отдельных запросов, а если у вас есть проблемы с производительностью, попробуйте оптимизировать.

Вы сами нашли решение ошибок при дозировании? Отправка 100 почтовых запросов по мобильному соединению для отображения стыков страницы - плохая идея.

Thomas Ahle 26.08.2011 12:24

Я добавляю ошибки в массив, перенаправляю пользователя на страницу с ошибкой 419 Conflict (и возвращаю эту ошибку клиенту) и отображаю массив ошибок. См. Мой ответ ниже для более подробной информации.

Eric Fuller 24.10.2013 19:45

Это нонсенс. Речь идет об отправке заказа на многие товары, которые, как многие говорили, вы можете просто в сущности одного запроса POST. Другое дело, как сервер обрабатывает это. В этом случае я не вижу проблем с созданием заказа, заполнением того, что вы можете для этого заказа, а также заполнением деталей, которые не могли быть выполнены. Таким образом, пользователь может увидеть свой заказ и увидеть, что все, кроме N товаров, были добавлены в заказ, но некоторые из них отсутствуют на складе или система не знает, что с ними делать. Еще один более простой, но менее удобный вариант - отклонить все

thecoshman 12.03.2014 19:16

@thecoshman сильно изменился за 3,25 года. Вероятно, вам стоит опубликовать полностью сформулированный ответ на вопрос.

dlamblin 22.07.2014 01:44

@dlamblin да, мне, наверное, нужно сделать много вещей ... Я доберусь до этого на каком-то этапе, может быть ...

thecoshman 22.07.2014 11:58

Есть несколько сценариев, в которых я могу подумать, что POST-публикация коллекции более эффективна. Например, если вы предоставляете веб-интерфейс CRUD для добавления списка продуктов (SKU, описание, цена за единицу) с помощью HandsOnTable (библиотека электронных таблиц JS), в этом случае пользователь ожидает просто скопировать / вставить пакет или большую часть продукты сразу. Вы, конечно, можете справиться с этим с помощью JS-клиента и сделать 1 запрос за раз, но это усложняется IMO, я лично предпочитаю оставить эту работу бэкэнд-REST API.

ivansabik 01.05.2017 02:43

Думаю, лучше отправлять отдельные запросы в одиночное соединение. Конечно, ваш веб-сервер должен это поддерживать.

Я действительно боролся с этим в последнее время, и вот над чем я работаю.

Если POST, который добавляет несколько ресурсов, завершается успешно, верните 200 OK (я рассматривал 201, но пользователь в конечном итоге не попадает на ресурс, который был создан) вместе со страницей, которая отображает все добавленные ресурсы, либо в режиме чтения -только или редактируемый мод. Например, пользователь может выбрать и отправить несколько изображений в галерею, используя форму, содержащую только один входной файл. Если запрос POST завершается успешно, пользователю предоставляется набор форм для каждого созданного представления ресурса изображения, что позволяет ему указать более подробную информацию о каждом (имя, описание и т. д.).

В случае, если не удается создать один или несколько ресурсов, обработчик POST прерывает всю обработку и добавляет каждое отдельное сообщение об ошибке в массив. Затем возвращается Конфликт 419, и пользователь перенаправляется на страницу ошибки 419 Конфликт, которая представляет содержимое массива ошибок, а также обратный путь к отправленной форме.

Facebook объясняет, как это сделать: https://developers.facebook.com/docs/graph-api/making-multiple-requests

Simple batched requests

The batch API takes in an array of logical HTTP requests represented as JSON arrays - each request has a method (corresponding to HTTP method GET/PUT/POST/DELETE etc.), a relative_url (the portion of the URL after graph.facebook.com), optional headers array (corresponding to HTTP headers) and an optional body (for POST and PUT requests). The Batch API returns an array of logical HTTP responses represented as JSON arrays - each response has a status code, an optional headers array and an optional body (which is a JSON encoded string).

Это очень интересная ссылка, предлагаемое решение мне кажется полезным. В любом случае, в StackOverflow предпочтительный ответ объясняет концепцию решения в теле ответа, поскольку ссылки могут измениться или исчезнуть.

Jan Vlcinsky 16.03.2016 00:57

Это действительно способ сделать это Facebook, не обязательно RESTful, как попросил OP.

0cd 07.03.2017 05:58

Я думаю, что пакетный API (от Google, Facebook и т. д. - @PuneetArora) более полезен при группировании нескольких несвязанных запросов вместе. Создание запроса, который создает один элемент, а затем группирование всех этих запросов вместе для отправки коллекции элементов - это «безумие» (Эйнштейн). Просто создайте запрос, который передает коллекцию элементов.

tim-montague 01.08.2017 20:03

Я считаю, что еще один правильный подход - создать еще один ресурс, представляющий вашу коллекцию ресурсов. Например, представьте, что у нас есть конечная точка, такая как /api/sheep/{id}, и мы можем выполнить POST на /api/sheep, чтобы создать ресурс овцы.

Теперь, если мы хотим поддерживать массовое создание, мы должны рассмотреть новый ресурс стада на /api/flock (или /api/<your-resource>-collection, если у вас нет более значимого имени). Помните, что ресурсы не нужно сопоставлять с вашей базой данных или моделями приложений. Это распространенное заблуждение.

Ресурсы - это представление более высокого уровня, не связанное с вашими данными. Работа с ресурсом может иметь значительные побочные эффекты, такие как запуск предупреждения для пользователя, обновление других связанных данных, запуск долгоживущего процесса и т. д. Например, мы могли бы сопоставить файловую систему или даже команду unix ps как REST API. .

Я думаю, можно с уверенностью предположить, что работа с ресурсом может также означать создание нескольких других сущностей в качестве побочного эффекта.

Я согласен с этим. Вы должны абстрагироваться от концепции коллекции вашего ресурса и относиться к ней как к ресурсу. Это также даст вам больше гибкости в будущем, когда вы захотите начать операции с этим и т. д.

villy393 06.10.2016 13:28

Это правильный подход. Это не нарушает запрос на сбор POST. Поскольку он используется для публикации одного объекта. Отправка массового запроса с использованием «отдельного массового объекта» - правильный подход.

Sorter 18.10.2016 14:54

Мне так нравится, как вы называете конечную точку api с помощью овец и отар! С некоторой степенью абстракции он почти имеет библейскую ссылку: «У меня есть другие овцы, которые не из этого загона; Я должен также привести их, и они услышат Мой голос; и станут одним стадом с одним пастырем». Иоанна 10:16.

Evgeny 30.09.2017 13:20

Интересно, что люди рекомендуют использовать форму множественного числа (коллекции) в URL-адресе, когда вы хотите создать один ресурс, например: отправить POST в / api / books для создания книги. Но затем, когда вы хотите создать 100 книг (в одном запросе как json), по какому URL-адресу вы разместите коллекцию из 100 книг? вот где начинается беспокойство.

code4kix 17.10.2018 16:54

@ code4kix вы можете использовать /api/book-group, /api/book-collection или что-то подобное.

miguelcobain 17.10.2018 17:31

Другие вопросы по теме