Я работаю над небольшой клиент-серверной программой для сбора заказов. Я хочу сделать это "REST (полностью) способом".
Что я хочу сделать:
Соберите все строки заказа (продукт и количество) и отправьте полный заказ на сервер
На данный момент я вижу два варианта сделать это:
На самом деле я не хочу этого делать, потому что хочу ограничить количество запросов к серверу, поэтому вариант 2:
Как реализовать вариант 2? у меня есть пара идей: Оберните все строки заказа в объект JSON и отправьте его на сервер или используйте массив для публикации строк заказа.
Является ли реализация варианта 2 хорошей идеей или хорошей практикой, и если да, то как мне это сделать.
Что такое хорошая практика?





Вы не захотите отправлять заголовки HTTP для 100 строк заказа. Вы также не хотите создавать больше запросов, чем необходимо.
Отправьте весь заказ в одном объекте JSON на сервер: server / order или server / order / new. Вернуть что-то, что указывает на: server / order / order_id
Также рассмотрите возможность использования СОЗДАЙТЕ PUT вместо POST
Нет? Ой, подождите, не было. Вместо этого были PUT.
Зачем вам использовать PUT для создания контента? Именно для этого и предназначен метод HTTP POST.
Вы используете PUT для создания ресурсов, когда хотите, чтобы клиент указывал URI ресурса, как в webdav. Я не согласен с использованием плаката PUT, но он имеет место при создании ресурсов, хотя это место может быть ограничено по объему.
@thecoshman, я думаю, он имеет в виду, что он изменяет коллекцию через PUT, но это должно заменить все ресурсы (а не добавлять ресурсы). Таким образом, используя ту же логику, мы должны вместо этого использовать PATCH, учитывая, что мы частично изменяем коллекцию, добавляя новые ресурсы.
@MhdSyrwan Нет, это совершенно новый порядок, нет существующего порядка для «PATCH», поэтому следует использовать либо PUT, либо POST. В этом случае ваш URL-адрес будет похож на /orders, вам все равно, какой URL-адрес назначен каждому отдельному заказу, поэтому POST будет выбором. Теперь, возможно, да, он модифицирует всю коллекцию заказов, однако «заказы» - это не единственный ресурс, и по этой логике можно утверждать, что все является частью корневого ресурса.
Примечание: POST-запрос объекта должен привести к тому, что объект станет подчиненным по отношению к ресурсу, указанному в запросе, и не будет идемпотентным. PUT заменяет объект по адресу и является идемпотентным. Идемпотентность (слово?) - важное ожидание потребителей.
Ваша идея кажется мне верной. Реализация - дело ваших предпочтений. Вы можете использовать JSON или просто параметры для этого (массив "order_lines []") и сделать
POST /orders
Поскольку вы собираетесь создать больше ресурсов одновременно в одном действии (порядке и его строках), жизненно важно проверять каждый из них и сохранять их только в том случае, если все они проходят проверку, т. Е. вы должны сделать это в транзакции.
Хотя массовые операции (например, пакетное создание) необходимы во многих системах, они формально не рассматриваются в архитектурном стиле RESTful.
Я обнаружил, что POSTing коллекции, как вы предложили, в основном работает, но проблемы возникают, когда вам нужно сообщить об ошибках в ответ на такой запрос. Такие проблемы усугубляются, когда происходит несколько сбоев по разным причинам или когда сервер не поддерживает транзакции. Я предлагаю вам, если нет проблем с производительностью, например, когда поставщик услуг находится в локальной сети (не в глобальной сети) или данные относительно малы, стоит отправить 100 запросов POST на сервер. Будьте проще, начните с отдельных запросов, а если у вас есть проблемы с производительностью, попробуйте оптимизировать.
Вы сами нашли решение ошибок при дозировании? Отправка 100 почтовых запросов по мобильному соединению для отображения стыков страницы - плохая идея.
Я добавляю ошибки в массив, перенаправляю пользователя на страницу с ошибкой 419 Conflict (и возвращаю эту ошибку клиенту) и отображаю массив ошибок. См. Мой ответ ниже для более подробной информации.
Это нонсенс. Речь идет об отправке заказа на многие товары, которые, как многие говорили, вы можете просто в сущности одного запроса POST. Другое дело, как сервер обрабатывает это. В этом случае я не вижу проблем с созданием заказа, заполнением того, что вы можете для этого заказа, а также заполнением деталей, которые не могли быть выполнены. Таким образом, пользователь может увидеть свой заказ и увидеть, что все, кроме N товаров, были добавлены в заказ, но некоторые из них отсутствуют на складе или система не знает, что с ними делать. Еще один более простой, но менее удобный вариант - отклонить все
@thecoshman сильно изменился за 3,25 года. Вероятно, вам стоит опубликовать полностью сформулированный ответ на вопрос.
@dlamblin да, мне, наверное, нужно сделать много вещей ... Я доберусь до этого на каком-то этапе, может быть ...
Есть несколько сценариев, в которых я могу подумать, что POST-публикация коллекции более эффективна. Например, если вы предоставляете веб-интерфейс CRUD для добавления списка продуктов (SKU, описание, цена за единицу) с помощью HandsOnTable (библиотека электронных таблиц JS), в этом случае пользователь ожидает просто скопировать / вставить пакет или большую часть продукты сразу. Вы, конечно, можете справиться с этим с помощью JS-клиента и сделать 1 запрос за раз, но это усложняется IMO, я лично предпочитаю оставить эту работу бэкэнд-REST API.
Думаю, лучше отправлять отдельные запросы в одиночное соединение. Конечно, ваш веб-сервер должен это поддерживать.
Я действительно боролся с этим в последнее время, и вот над чем я работаю.
Если 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 предпочтительный ответ объясняет концепцию решения в теле ответа, поскольку ссылки могут измениться или исчезнуть.
Это действительно способ сделать это Facebook, не обязательно RESTful, как попросил OP.
Я думаю, что пакетный API (от Google, Facebook и т. д. - @PuneetArora) более полезен при группировании нескольких несвязанных запросов вместе. Создание запроса, который создает один элемент, а затем группирование всех этих запросов вместе для отправки коллекции элементов - это «безумие» (Эйнштейн). Просто создайте запрос, который передает коллекцию элементов.
Я считаю, что еще один правильный подход - создать еще один ресурс, представляющий вашу коллекцию ресурсов.
Например, представьте, что у нас есть конечная точка, такая как /api/sheep/{id}, и мы можем выполнить POST на /api/sheep, чтобы создать ресурс овцы.
Теперь, если мы хотим поддерживать массовое создание, мы должны рассмотреть новый ресурс стада на /api/flock (или /api/<your-resource>-collection, если у вас нет более значимого имени). Помните, что ресурсы не нужно сопоставлять с вашей базой данных или моделями приложений. Это распространенное заблуждение.
Ресурсы - это представление более высокого уровня, не связанное с вашими данными. Работа с ресурсом может иметь значительные побочные эффекты, такие как запуск предупреждения для пользователя, обновление других связанных данных, запуск долгоживущего процесса и т. д. Например, мы могли бы сопоставить файловую систему или даже команду unix ps как REST API. .
Я думаю, можно с уверенностью предположить, что работа с ресурсом может также означать создание нескольких других сущностей в качестве побочного эффекта.
Я согласен с этим. Вы должны абстрагироваться от концепции коллекции вашего ресурса и относиться к ней как к ресурсу. Это также даст вам больше гибкости в будущем, когда вы захотите начать операции с этим и т. д.
Это правильный подход. Это не нарушает запрос на сбор POST. Поскольку он используется для публикации одного объекта. Отправка массового запроса с использованием «отдельного массового объекта» - правильный подход.
Мне так нравится, как вы называете конечную точку api с помощью овец и отар! С некоторой степенью абстракции он почти имеет библейскую ссылку: «У меня есть другие овцы, которые не из этого загона; Я должен также привести их, и они услышат Мой голос; и станут одним стадом с одним пастырем». Иоанна 10:16.
Интересно, что люди рекомендуют использовать форму множественного числа (коллекции) в URL-адресе, когда вы хотите создать один ресурс, например: отправить POST в / api / books для создания книги. Но затем, когда вы хотите создать 100 книг (в одном запросе как json), по какому URL-адресу вы разместите коллекцию из 100 книг? вот где начинается беспокойство.
@ code4kix вы можете использовать /api/book-group, /api/book-collection или что-то подобное.
Я полагаю, это метод HTTP POST. Не существует такой вещи, как метод CREATE HTTP.