Чи нормально частково змінити колекцію за допомогою PUT або DELETE?


21

У мене є колекція продуктів у групі продуктів, наприклад:

product-groups/123/products
  1. Якщо мені потрібно додати до колекції, чи добре, що я передаю лише деякі продукти з PUT?

  2. Якщо мені потрібно видалити деякі продукти з колекції, чи гаразд я передаю дані фільтру (масив ідентифікаторів) із DELETE?

Який найкращий спосіб реалізувати функціональність у дусі ReST?

Редагувати: елементи - це посилання на окремі об'єкти, в основному ідентифікатори продуктів.


Чи предметами в групі продуктів окремі ресурси керуються в іншому місці? Або вони є лише частиною колекції групи товарів? Чи можуть товари належати до кількох груп товарів?
Martijn Pieters

2
можливо PATCH Ця специфікація визначає новий метод HTTP / 1.1 [RFC2616] PATCH, який використовується для застосування часткових модифікацій до ресурсу.
Есаїлія

Продукт (ідентифікатор) може належати до кількох груп товарів.
користувач151851

Чи є відомий спосіб (найкраща практика) сказати, як ПАТЧ, тобто додавати або видаляти продукти в колекцію?
користувач151851

Схожий питання на SO stackoverflow.com/questions/411462 / ...
Luke Puplett

Відповіді:


10

Загалом у вас є одна кінцева точка, яка представляє всю колекцію x :

/products

Скажімо, ви хочете оновити один продукт, ви робите PUT до /products/{id}. Якщо ви хочете частково оновити один продукт (не оновлюючи кожне поле), ви також можете використовувати PATCH для /products/{id}. Те ж саме стосується видалення однієї сутності ( DELETE to /products/{id}).

Якщо ви хочете націлити один ресурс, ви маєте право через шлях, який єдиний ресурс ви хочете змінити.

Єдина дія, яка порушує схему, - це створення ресурсу. Створюючи ресурс, ви орієнтуєтеся на колекцію в цілому, скажімо, POST на /products.

З огляду на це, повинно бути зрозуміло, що ціль для операцій, що впливають на колекцію в цілому, повинна відповідати відповідній кінцевій точці збору.

Наприклад, ви хочете отримати підмножину продуктів червоного кольору, ви запитаєте її

GET до /products?colour=red.

Отже, якщо ви хочете видалити все це, ви ВИДАЛИМО /products?colour=red . Або якщо ви хочете видалити деякі продукти за допомогою id, ви можете ВІДКРИТИ /products?id=1&id=2&id=3 .

А як щодо масового створення ресурсів? Розмістіть свою колекцію [{...},{...},{...}]просто на /products. Те саме стосується PUT і PATCH .

Це справді просто.

Щоб відповісти на ваші запитання:

Якщо мені потрібно додати до колекції, чи добре, що я передаю лише деякі продукти з PUT?

Це не тільки добре, вас заохочують робити так.

Якщо мені потрібно видалити деякі продукти з колекції, чи гаразд я передаю дані фільтру (масив ідентифікаторів) із DELETE?

Це добре. Як писав Енеко Алонсо, іноді трапляються обкладинки, інкапсульовані через "контролер" - кінцеві точки, тобто для запуску (складних) операцій використовується POST .


2
PUT - це операція заміни. Виклик PUT на кінцевій точці колекції з "деякими продуктами" повинен видалити (у випадку ОП, видалити відношення до) будь-якого продукту, який не входить до списку "деяких продуктів". Хоча його можна використовувати для додавання елементів, він також повинен видаляти елементи, які не (на мій погляд) очікуються в ОП. Вам слід переглянути свою відповідь на їх перше запитання відповідно.
claytond

@claytond: Я вважаю, що відповідь хороший, якщо буде зроблено часткове оновлення PATCH, а також повна заміна через PUT.
9000

4
@ 9000. Звичайно, але відповідь на даний момент говорить: "Вам рекомендується ... додати до колекції ... [мимо] передайте [ing] лише деякі продукти з PUT". Це, звичайно, неправильно. Заохочується до POST. Здатний PUT ... але тільки передаючи всі (не деякі) елементи.
claytond

5

Зазвичай методи REST мають намір працювати над однією сутністю / об'єктом (CRUD).

Є кілька варіантів:

  • Ставтесь до своїх колекцій як до об'єктів та оновлюйте їх через POST
  • Створюйте альтернативні операції, які не є REST

Перший відповідає стандартам REST, але може бути дорогим, оскільки об’єкти / об'єкти колекції можуть бути дуже великими (оновлення групи, яка містить тисячі продуктів лише для додавання / видалення одного продукту, буде великим запитом).

Другий варіант надається перевагою багатьма API, як спосіб розширити REST за межами операцій CRUD.

Наприклад:

GET product-groups/123/products (list all the products in the group)
POST product-groups/123/products/append (POST a list of new product ids to append to the group)
POST product-groups/123/products/remove (POST a list of product ids to remove from the group)

Багато API використовують завжди POST для цієї розширеної операції, але ніщо не обмежує вас використовувати інші методи http (крім обмеження GET і DELETE, щоб мати порожнє тіло)


Звичайно, існує кілька методів, щоб досягти мети. Яка найкраща практика? Хто з них буде більш стійким до майбутнього?
користувач151851

4
@ user151851: Загальна відповідність REST (якщо така є) є високою метою. Структура підходу тут здається більш реалістичною, оскільки вона намагається використовувати підхід, який фактично використовується в "реальному світі", що робить його, по суті, дефакто-стандартом. Це приблизно таке майбутнє, як ви збираєтеся отримати.
Роберт Харві

2
Чи не ми вводимо власні дієслова, використовуючи "додавати" та "видаляти" в URL-адресі? Таким чином нам доведеться пояснити, як використовувати API. Чи не слід повторно використовувати те, що ми маємо, тобто методи HTTP? У цьому випадку дії добре відомі.
користувач151851

7
Для всіх, хто стикається з цією відповіддю: Це неправильно. Як зазначалося @ user151851, це вводить дієслова в URL-адресу, яка настільки ж не RESTful, як ви можете отримати. Що стосується власне питання, то я не маю великої відповіді, але це не все.
umbrae

Чи може "розширення" бути більш орієнтованим на ресурси, зробивши його, products/collectionяке повертає "конверт" елементів, а зміст конверта змінюється через PUT? Мовляв, "ось як я хочу, щоб були предмети в колекції".
Люк Пуплетт

3

Просто для точного попередніх відповідей / коментарів.

Згідно з моїми знаннями, POST - це метод додавання окремих елементів до колекції.

DELETE в свою чергу - це метод видалення одного елемента з колекції. Обидва сценарії ідеально RESTful.

Однак ви повинні використовувати відповідний URI для позначення одного елемента або всієї колекції.

Наприклад, щоб додати елемент до колекції, ви повинні розмістити дані POST у наступному URI:

https://www.factory.net/products/

Щоб видалити окремий продукт із колекції, ви можете використовувати метод DELETE для надсилання запиту на щось на зразок:

https://www.factory.net/products/108/

Метод PATCH може використовуватися для оновлення деяких елементів колекції. Наприклад, коли вам потрібно оновити лише одне поле в одному елементі. ВСТАНОВЛЕННЯ повного представлення ресурсів для дуже великої колекції може бути дуже дорогою операцією.


2

В принципі, всі операції RESTful дійсні для колекції, але переконайтеся, що ви розумієте, як семантика дієслів застосовується до колекції:

  • PUT - це повна заміна.

    • Якщо ви перейдете на сингл (наприклад /item/{id}) і не виймете nameйого, його слід очистити або встановити на нуль або щось подібне.
    • Якщо ви PUT до колекції і не включаєте предмет, його слід видалити з цієї колекції.

    Хоча PUT можна використовувати для додавання елементів, ви повинні надіслати "всі" елементи. Відправлення "деяких" елементів має призвести до видалення (я припускаю, що це не те, що бажає ОП).

  • DELETE більш інтуїтивно зрозумілий. Дійсно видалити колекцію або будь-яку її відфільтровану підмножину. Потрібно впливати лише на елементи, включені до фільтра.

  • PATCH також діє. Теоретично ви повинні надати список "операцій". Наприклад, ви повинні технічно надіслати щось на кшталт:

    [{ 
        "action": "update",
        "id": <id>,
        "value": {...}
    },{
        "action": "add",
        "value": {...}
    }, ...]
    

    На практиці частіше бачити API, який приймає частковий список об'єктів, де кожен елемент обробляється за допомогою логіки UPSERT (оновлення або вставки).

  • Технічно POST повинен обробляти вхід "відповідно до власної специфіки семантики".

    • На практиці POST зазвичай використовується для операцій "створення".
    • Однак POST - це також дієслово, яке використовується для нестандартних дзвінків. Хоча ведуться бурхливі суперечки щодо того, чи є кінцеві точки дії строго RESTful (я сторони з "no" s), POST є відповідним дієсловом, якщо ви надсилали запит у подібну кінцеву точку {resource}/activate.

ПРИМІТКА. Під час використання операцій, що не належать до GET, у колекціях уважно враховуйте визначення успіху та невдачі. REST не дає вам гарного способу спілкування з частковим успіхом. Хорошим замовчуванням є припущення, що ви будете запускати операцію з трансакцією за критеріями успіху або майже нічого. Якщо це не те, що ви хочете, ви, ймовірно, не повинні безпосередньо взаємодіяти з колекцією.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.