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


122

Я працюю над невеликою клієнтською серверною програмою для збору замовлень. Я хочу це зробити "REST (ful) способом".

Що я хочу зробити:

Зберіть всі замовні лінії (товар і кількість) і відправте повне замовлення на сервер

На даний момент я бачу два варіанти для цього:

  1. Надішліть кожну лінію замовлення на сервер: POST qty та product_id

Я насправді не хочу цього робити, тому що хочу обмежити кількість запитів до сервера, тому варіант 2:

  1. Зберіть всі замовні лінії та одразу надішліть їх на сервер.

Як слід реалізувати варіант 2? у мене є кілька ідей: загортайте всі порядкові лінії в об’єкт JSON і відправте це на сервер або використовуйте масив для розміщення рядків замовлення.

Чи є гарною ідеєю чи хорошою практикою реалізація варіанту 2, і якщо так, як мені це зробити.

Що таке хороша практика?

rest  post 

Відповіді:


74

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

Тепер, якщо ми хочемо підтримати масове створення, ми повинні розглянути новий ресурс flock за адресою /api/flock(або /api/<your-resource>-collectionякщо вам не вистачає кращого змістовного імені). Пам’ятайте, що ресурси не потрібно відображати у вашій базі даних чи моделях додатків . Це поширена помилка.

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

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


Я згоден з цим. Ви повинні абстрагувати концепцію колекції вашого ресурсу і ставитися до цього як до ресурсу. Це дасть вам більше гнучкості і в майбутньому, коли ви захочете почати робити операції над цим тощо
villy393

Це правильний підхід. Це не порушує запит на колекцію POST. Оскільки він використовується для розміщення однієї сутності. Надсилання групового запиту з "окремою масовою суттю" - це правильний підхід.
Сортер

2
Мені подобається, що ти кінцеву точку api називаєш так багато овець і овець! Зі ступенем абстракції це майже має біблійне посилання: "У мене є інші вівці, які не з цієї складки; я повинен принести їх і вони, і вони почують Мій голос; і вони стануть однією зграєю з одним пастухом". Івана 10:16.
Євгеній

1
Цікаво, що люди рекомендують використовувати форму множини (колекції) в URL-адресі, коли ви хочете створити єдиний ресурс, як-от так: надішліть POST в / api / books, щоб створити книгу. Але тоді, коли ви хочете створити 100 книг (в одному запиті як json), на яку URL-адресу ви б опублікували колекцію з 100 книг? ось тут починається неспокій.
code4kix

@ Code4kix ви могли б використовувати /api/book-group, /api/book-collectionабо що - щось подібне.
miguelcobain

46

Хоча масові операції (наприклад, створення пакетів) є важливими для багатьох систем, вони формально не вирішені стилем архітектури RESTful.

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


3
Ви самі знайшли рішення щодо помилок у разі дозування? На мобільному з'єднанні, що надсилає 100 запитів на пошту, щоб показати шви сторінки, як погана ідея.
Томас Ейл

Я додаю помилки до масиву, перенаправляю користувача на сторінку помилки 419 Conflict (і повертаю цю помилку клієнту) та відображаю масив помилок. Дивіться мою відповідь нижче для більш детальної інформації.
Ерік Фуллер

5
Це нісенітниця. Питання полягає в надсиланні замовлення на багато предметів, яке, як уже багато хто сказали, ви можете просто в суті одного запиту POST. Як сервер обробляє це цілком інша справа. У цьому випадку я не бачу проблем із створенням замовлення, заповненням того, що ви можете для цього замовлення, а також заповненням деталей, які неможливо було виконати. Таким чином користувач може бачити їх замовлення і бачити, що всі замовлення, крім N, були додані до замовлення, але деякі з них відсутні на складі, або система не знала, що робити. Ще один простіший, але менш зручний варіант - відхилити все
thecoshman

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

3
@dlamblin Так, я, мабуть, мабуть робити багато речей ... Я, можливо,
доїду

9

Facebook пояснює, як це зробити: https://developers.facebook.com/docs/graph-api/making-multiple-requests

Прості пакетні запити

Пакетний API приймає масив логічних запитів HTTP, представлених як масиви JSON - кожен запит має метод (відповідний методу HTTP GET / PUT / POST / DELETE тощо), rela_url (частина URL після graph.facebook. com), необов'язковий масив заголовків (що відповідає заголовкам HTTP) та необов'язкове тіло (для запитів POST та PUT). Пакетний API повертає масив логічних відповідей HTTP, представлених як масиви JSON - у кожній відповіді є код статусу, необов'язковий масив заголовків та необов'язкове тіло (що є кодованим рядком JSON).


1
Це дуже цікаве посилання, запропоноване рішення мені здається корисним. У будь-якому випадку, у StackOverflow переважна відповідь пояснює поняття рішення в тілі відповіді, оскільки посилання можуть змінюватися або зникати.
Ян Вльчинський

7
Це дійсно спосіб Facebook зробити це, не обов'язково ВИБУДОВИЙ, як просив ОП
0cd

Я думаю, що пакетний API (від Google, Facebook тощо) - @PuneetArora) є більш корисним при групуванні кількох непов'язаних запитів разом. Створити запит, який створює один елемент, а потім згрупувати всі ці запити разом, щоб надіслати колекцію предметів, це "божевілля" (Ейнштейн). Просто створіть запит, який передає колекцію елементів.
tfmontague

8

Ваша ідея здається мені справедливою. Реалізація - це питання ваших уподобань. Ви можете використовувати JSON або просто параметри для цього ("order_lines []" масив) і зробити

POST /orders

Оскільки ви збираєтесь створити більше ресурсів одразу за одну дію (порядок та її рядки), важливо перевірити кожен із них та зберегти їх лише у тому випадку, якщо всі вони проходять перевірку, тобто. ви повинні робити це в операції.



5

Я фактично боровся з цим останнім часом, і ось над чим я працюю.

Якщо POST, який додає кілька ресурсів, успішний, поверніть 200 ОК (я розглядав 201, але в кінцевому підсумку користувач не приземляється на створений ресурс) разом зі сторінкою, на якій відображаються всі додані ресурси, читання -тільки або редагована мода. Наприклад, користувач може вибрати та розмістити декілька зображень у галереї, використовуючи форму, що містить лише один вхідний файл. Якщо POST-запит успішно виконаний, користувачеві надається набір форм для кожного створеного представлення ресурсу зображення, що дозволяє їм задавати більше деталей щодо кожного (ім'я, опис тощо).

У випадку, якщо один або більше ресурсів не вдасться створити, обробник POST припиняє всю обробку і додає кожне окреме повідомлення про помилку до масиву. Потім повертається конфлікт 419, і користувач перенаправляється на сторінку помилки 419 Conflict, яка представляє вміст масиву помилок, а також зворотний шлях до форми, що була подана.


-2

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

Відправити все замовлення в одному об’єкті JSON на сервер на: сервер / замовлення або сервер / замовлення / новий. Поверніть щось, що вказує на: server / order / order_id

Також розгляньте можливість використання CREATE PUT замість POST


Я припускаю, що він використовує метод HTTP POST. Не існує такого поняття, як CREATE HTTP method.
Мілан Новота

Хіба немає? О, чекайте, не було. Натомість були PUT.
Веселий

22
Чому на землі ви б використовували PUT для створення вмісту? Саме для цього призначений метод HTTP POST.
thecoshman

8
Ви використовуєте PUT для створення ресурсів, коли хочете, щоб клієнт вказав URI ресурсу, як, наприклад, у webdav. Я не погоджуюся з використанням плакатом PUT плаката, але він має місце у створенні ресурсів, хоча це місце може бути обмеженим за обсягом.
користувач602525

2
Примітка. Розміщення суб'єкта господарювання повинно призвести до того, що суб'єкт господарювання стає підлеглим ресурсу, на який звертається запит, і не є ідентичним. PUT замінює сутність за адресою та є ідентичною. Ідентифікація (слово?) Є важливим очікуванням для споживачів.
Люк Пуплетт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.