Моделювання операцій у службі REST

Я знаю, що такі питання були поставлені раніше. У мене є рішення для моєї проблеми, і я хочу знати, якщо я порушую REST або HTTP принципи в будь-якому місці.

У моїй системі є ресурс з назвою member , який підтримує звичайні операції GET/POST/PUT . Член має статус Активна і Вимкнено . Мені потрібно моделювати операцію відключення користувача. Я розумію, чому наступне було б поганою ідеєю з точки зору REST

POST api/member/john.smith/disable

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

public class DisableMemberRequest
{
    public string Username {get; set;}
}

А потім POST на вищевказаному ресурсі

POST api/DisableMemberRequest

Хоча цей підхід звучить розумно, я вважаю, що це не правильно з точки зору чистого інтерфейсу API. Може бути спірним, чи повинен відповідь на вищезазначений запит бути 200 OK або 201 Створений або 202 Accepted .

Я думаю, я б створив новий ресурс під назвою DisabledMember , а PUT на цьому ресурсі означатиме, що певний член повинен бути вимкнений, як зазначено нижче

PUT api/disabledmember/john.smith

Це виглядає як цілком правильний дизайн з точки зору REST/HTTP для мене. Але я не експерт і хотів би підтвердити це з людьми, які робили це протягом тривалого часу.

EDIT

Я додаю ці деталі після взаємодії з іншими програмістами на цій сторінці. Процес відключення члена - це не лише встановлення прапора стану на члені. Існують інші робочі процеси, які потрібно активувати, коли член вимкнено.

7

9 Відповіді

Одним із способів, яким я люблю робити такі речі, є визначення ресурсу, який представляє безліч недієздатних членів. Щоб вимкнути член, ви можете додати його до набору користувачів з обмеженими можливостями. Це може виглядати приблизно так.

POST /api/DisabledMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Якщо ви хочете змінити операцію, ви можете це зробити

POST /api/ActiveMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Цей підхід має вигоду з того факту, що робити GET/api/DisabledMembers було б абсолютно природною справою. Крім того, за допомогою text/uri-list стає легко відключити/повторно активувати набір членів одночасно.

4
додано
Дозвольте мені отримати це право. Ви пропонуєте, щоб PUT рекомендувалося мати деяке корисне навантаження, тоді як POST нормально без корисного навантаження? Я не дуже зрозуміла в цьому аспекті. Чи є якась стаття/блог, яка більше розповідає про цей аспект?
додано Автор Suhas, джерело
Причина, по якій я використовую PUT , полягає в тому, що ідентифікатор ресурсу, який буде створено під час обробки цього запиту, відомий клієнту, або, іншими словами, ви PUT називають URL. POST зазвичай використовується, коли клієнт не знає URL-адресу ресурсу, який буде створено.
додано Автор Suhas, джерело
Що схоже на те, що я планую зробити. Різниця лише в тому, що ви використовуєте POST замість PUT
додано Автор Suhas, джерело
@Suhas Який тип медіа ви б PUT? Я вважаю, що ви могли б PUT з порожнім тілом і DELETE для повторної активації.
додано Автор Darrel Miller, джерело
@Suhas обидві досить рідкісні. Проте, наскільки я знаю, специфікація HTTP також не заперечує.
додано Автор Darrel Miller, джерело
@suhas PUT цілком правильний. Як ви згадуєте, легко легко побудувати uri заздалегідь, і це ідемпотентно. Отже, PUT є більш репрезентативною для семантики. Тільки дивна річ, як правило, з PUT ви ставите те, що ви хочете зберігати. У вашому випадку, дія робити PUT є тим, що є значним. Там дійсно немає необхідності в корисному навантаженні.
додано Автор Darrel Miller, джерело

Одним із способів, яким я люблю робити такі речі, є визначення ресурсу, який представляє безліч недієздатних членів. Щоб вимкнути член, ви можете додати його до набору користувачів з обмеженими можливостями. Це може виглядати приблизно так.

POST /api/DisabledMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Якщо ви хочете змінити операцію, ви можете це зробити

POST /api/ActiveMembers
Content-Type: text/uri-list

http://example.org/api/members/john.smith

Цей підхід має вигоду з того факту, що робити GET/api/DisabledMembers було б абсолютно природною справою. Крім того, за допомогою text/uri-list стає легко відключити/повторно активувати набір членів одночасно.

4
додано
Дозвольте мені отримати це право. Ви пропонуєте, щоб PUT рекомендувалося мати деяке корисне навантаження, тоді як POST нормально без корисного навантаження? Я не дуже зрозуміла в цьому аспекті. Чи є якась стаття/блог, яка більше розповідає про цей аспект?
додано Автор Suhas, джерело
Причина, по якій я використовую PUT , полягає в тому, що ідентифікатор ресурсу, який буде створено під час обробки цього запиту, відомий клієнту, або, іншими словами, ви PUT називають URL. POST зазвичай використовується, коли клієнт не знає URL-адресу ресурсу, який буде створено.
додано Автор Suhas, джерело
Що схоже на те, що я планую зробити. Різниця лише в тому, що ви використовуєте POST замість PUT
додано Автор Suhas, джерело
@Suhas обидві досить рідкісні. Проте, наскільки я знаю, специфікація HTTP також не заперечує.
додано Автор Darrel Miller, джерело
@suhas PUT цілком правильний. Як ви згадуєте, легко легко побудувати uri заздалегідь, і це ідемпотентно. Отже, PUT є більш репрезентативною для семантики. Тільки дивна річ, як правило, з PUT ви ставите те, що ви хочете зберігати. У вашому випадку, дія робити PUT є тим, що є значним. Там дійсно немає необхідності в корисному навантаженні.
додано Автор Darrel Miller, джерело
@Suhas Який тип медіа ви б PUT? Я вважаю, що ви могли б PUT з порожнім тілом і DELETE для повторної активації.
додано Автор Darrel Miller, джерело

Ваші перші дві пропозиції трохи пахнуть, тому що вони мають дієслово в URL. Гарна архітектура RESTful визначає тільки імена подібних ресурсів, оскільки протокол HTTP визначає набір дієслів, застосовних до цих ресурсів.

Інша пропозиція цікава, але PUT пропонує вам виконати GET , щоб отримати уявлення про те, що ви щойно розмістили там, що не робить багато сенс у цьому контексті.

З того, що ви говорите, існує значний процес увімкнення або вимкнення облікового запису користувача, і вам не сподобається, що це операція PUT або PATCH для простого " переверніть "значення від true до false . Якщо це займе деякий час, має перехідний стан і, ймовірно, буде те, що ви хочете виставити споживачам API, щоб вони знали про цей процес, має сенс визначити сам процес як вид ресурсу:

Почати деактивацію:

POST api/members/deactivations

Отримати поточний стан деактивації або звітувати про заходи, які відбулися:

GET api/members/deactivations/john.smith

Скасувати деактивацію, що протікає (необов'язково):

DELETE api/members/deactivations/john.smith

Якщо ви можете повторно активувати обліковий запис, він може слідувати подібному шаблону.

Якщо ви відчуваєте, що для цих робочих процесів не вистачає змісту, щоб виправдати їх як власні ресурси, або ви просто не знаєте, що потрібно поставити у відповідь на GET , це означає, що робочий процес не настільки значним, що його не можна просто приховати від користувачів API і викликати як побічний ефект зміни значення active користувача.

3
додано
Відмінність полягає в тому, що деактивація - це явна річ, яку ви можете зрозуміти, незалежно від інших ресурсів, але все ще сильно пов'язана з членами .
додано Автор Paul Turner, джерело
Я думаю, що я називаю DisableMemberRequest , ви викликаєте деактивацію . Мені подобається використовувати DELETE для скасування процесу деактивації. Але знову це корисно, якщо деактивація є тривалим процесом.
додано Автор Suhas, джерело

Ваші перші дві пропозиції трохи пахнуть, тому що вони мають дієслово в URL. Гарна архітектура RESTful визначає тільки імена подібних ресурсів, оскільки протокол HTTP визначає набір дієслів, застосовних до цих ресурсів.

Інша пропозиція цікава, але PUT пропонує вам виконати GET , щоб отримати уявлення про те, що ви щойно розмістили там, що не робить багато сенс у цьому контексті.

З того, що ви говорите, існує значний процес увімкнення або вимкнення облікового запису користувача, і вам не сподобається, що це операція PUT або PATCH для простого " переверніть "значення від true до false . Якщо це займе деякий час, має перехідний стан і, ймовірно, буде те, що ви хочете виставити споживачам API, щоб вони знали про цей процес, має сенс визначити сам процес як вид ресурсу:

Почати деактивацію:

POST api/members/deactivations

Отримати поточний стан деактивації або звітувати про заходи, які відбулися:

GET api/members/deactivations/john.smith

Скасувати деактивацію, що протікає (необов'язково):

DELETE api/members/deactivations/john.smith

Якщо ви можете повторно активувати обліковий запис, він може слідувати подібному шаблону.

Якщо ви відчуваєте, що для цих робочих процесів не вистачає змісту, щоб виправдати їх як власні ресурси, або ви просто не знаєте, що потрібно поставити у відповідь на GET , це означає, що робочий процес не настільки значним, що його не можна просто приховати від користувачів API і викликати як побічний ефект зміни значення active користувача.

3
додано
Відмінність полягає в тому, що деактивація - це явна річ, яку ви можете зрозуміти, незалежно від інших ресурсів, але все ще сильно пов'язана з членами .
додано Автор Paul Turner, джерело
Я думаю, що я називаю DisableMemberRequest , ви викликаєте деактивацію . Мені подобається використовувати DELETE для скасування процесу деактивації. Але знову це корисно, якщо деактивація є тривалим процесом.
додано Автор Suhas, джерело

Просто відповіли на аналогічне запитання в тут .

Практичний спосіб мислення або застосування REST як вихідної точки (принаймні, для мене це працює) - це думати наступним чином:

1) Використовуйте лише HTTP "GET/POST/PUT/DELETE" як спосіб моделювання доменних дій. Як і у випадку з базою даних, всі ваші дії відображаються на CURD .

2) URI/URL - це лише ідентифікація ресурсів. У вашому URI ніколи не повинно бути "дій".

3) Обмінювані дані повинні бути в тілі HTTP-повідомлень. Просто для спрощення обговорення, а не про те, як моделювати самі дані

Рішення Трагедіана виглядає чистим.

Оновлено для адреси коментарів @Suhas

REST не йде про конвенцію про найменування. Мова йде про те, як подумати про ресурси замість «дій» при розробці REST API. Потрібно завжди думати про ресурс, подібний до "Nonce", у URL/URI. Ви вже маєте всі дії CURD, до яких слід додати дії домену та маніпулювати ресурсами в URL-адресі.

Мені подобається рішення Tragedian, тільки для обговорення, ми можемо рефактори рішення Tragedian з подібним набором nonce і різних URL шаблон, щоб "краще" вписується в різних доменів використання. Наступне може бути не найкращим рішенням для домену, але вони є еквівалентними RESTful.

Видалити членство

  • DELETE api/membership/[member-id]/

Отримати статус учасника

  • GET api/members/[member-id]/status/

Додати членство

  • POST api/members/[member-id]/

Оновлено для вирішення проблеми з "DisabledMember" як ресурс

Якщо використовувати "PUT DisabledMember", щоб зробити "вимкнути член", як це запропонував Сухас Тоді, що означатимуть наступні дії на ресурсі "DisabledMember"?

DELETE DisabledMember → активуйте його знову ??

POST DisabledMember -> ??

GET DisabledMember - це легко☺

Завдяки такому проекту він фактично "маскує" дію "відключити" в ресурсі. Ви все ще можете змусити придатний, щоб робити те, що ви хочете, але це не буде, як Restful для мене.

1
додано
Коли я сказав, що маю на увазі тільки "з ділових причин". Напр. Якщо я забороняю DELETE на DisabledMember , це буде з бізнес-причин.
додано Автор Suhas, джерело
Чи повинен кожний ресурс підтримувати кожну HTTP-дію? DELETE/POST на DisabledMember просто поверне HTTP 405 Не дозволено
додано Автор Suhas, джерело
Я розумію вашу точку зору на проектування навколо ресурсу. Але я не бачу коментарів щодо моєї третьої конструкції, що стосується введення нового ресурсу під назвою DisabledMember . Чи є якісь проблеми з цим дизайном?
додано Автор Suhas, джерело
Я думаю, що єдина відмінність між моїм другим рішенням і рішенням трагедія полягає в тому, що він має кращу угоду про іменування.
додано Автор Suhas, джерело
REST не йде про конвенцію про найменування. Мова йде про те, як подумати про ресурси замість «дій» при розробці REST API. Потрібно завжди думати про ресурс, подібний до "Nonce", у URL/URI. Ви вже маєте всі дії CURD, до яких слід додати дії домену та маніпулювати ресурсами в URL-адресі.
додано Автор Ming Chan, джерело
З дизайном "DisabledMember" він фактично "маскує" дію "відключити" в ресурсі. Ви все ще можете змусити придатний, щоб робити те, що ви хочете, але це не буде, як Restful для мене.
додано Автор Ming Chan, джерело
Він не повинен, але це буде більше з бізнес-логіки причин; наприклад, щоб заборонити Delete, це може бути, що це не дозволяє "видалити" цей конкретний ресурс після його створення. Я зазвичай розглядаю назву ресурсу, розглядаючи всі дієслова CURD, щоб допомогти зробити вибір дизайну.
додано Автор Ming Chan, джерело

Просто відповіли на аналогічне запитання в тут .

Практичний спосіб мислення або застосування REST як вихідної точки (принаймні, для мене це працює) - це думати наступним чином:

1) Використовуйте лише HTTP "GET/POST/PUT/DELETE" як спосіб моделювання доменних дій. Як і у випадку з базою даних, всі ваші дії відображаються на CURD .

2) URI/URL - це лише ідентифікація ресурсів. У вашому URI ніколи не повинно бути "дій".

3) Обмінювані дані повинні бути в тілі HTTP-повідомлень. Просто для спрощення обговорення, а не про те, як моделювати самі дані

Рішення Трагедіана виглядає чистим.

Оновлено для адреси коментарів @Suhas

REST не йде про конвенцію про найменування. Мова йде про те, як подумати про ресурси замість «дій» при розробці REST API. Потрібно завжди думати про ресурс, подібний до "Nonce", у URL/URI. Ви вже маєте всі дії CURD, до яких слід додати дії домену та маніпулювати ресурсами в URL-адресі.

Мені подобається рішення Tragedian, тільки для обговорення, ми можемо рефактори рішення Tragedian з подібним набором nonce і різних URL шаблон, щоб "краще" вписується в різних доменів використання. Наступне може бути не найкращим рішенням для домену, але вони є еквівалентними RESTful.

Видалити членство

  • DELETE api/membership/[member-id]/

Отримати статус учасника

  • GET api/members/[member-id]/status/

Додати членство

  • POST api/members/[member-id]/

Оновлено для вирішення проблеми з "DisabledMember" як ресурс

Якщо використовувати "PUT DisabledMember", щоб зробити "вимкнути член", як це запропонував Сухас Тоді, що означатимуть наступні дії на ресурсі "DisabledMember"?

DELETE DisabledMember → активуйте його знову ??

POST DisabledMember -> ??

GET DisabledMember - це легко☺

Завдяки такому проекту він фактично "маскує" дію "відключити" в ресурсі. Ви все ще можете змусити придатний, щоб робити те, що ви хочете, але це не буде, як Restful для мене.

1
додано
Коли я сказав, що маю на увазі тільки "з ділових причин". Напр. Якщо я забороняю DELETE на DisabledMember , це буде з бізнес-причин.
додано Автор Suhas, джерело
Чи повинен кожний ресурс підтримувати кожну HTTP-дію? DELETE/POST на DisabledMember просто поверне HTTP 405 Не дозволено
додано Автор Suhas, джерело
Я розумію вашу точку зору на проектування навколо ресурсу. Але я не бачу коментарів щодо моєї третьої конструкції, що стосується введення нового ресурсу під назвою DisabledMember . Чи є якісь проблеми з цим дизайном?
додано Автор Suhas, джерело
Я думаю, що єдина відмінність між моїм другим рішенням і рішенням трагедія полягає в тому, що він має кращу угоду про іменування.
додано Автор Suhas, джерело
REST не йде про конвенцію про найменування. Мова йде про те, як подумати про ресурси замість «дій» при розробці REST API. Потрібно завжди думати про ресурс, подібний до "Nonce", у URL/URI. Ви вже маєте всі дії CURD, до яких слід додати дії домену та маніпулювати ресурсами в URL-адресі.
додано Автор Ming Chan, джерело
З дизайном "DisabledMember" він фактично "маскує" дію "відключити" в ресурсі. Ви все ще можете змусити придатний, щоб робити те, що ви хочете, але це не буде, як Restful для мене.
додано Автор Ming Chan, джерело
Він не повинен, але це буде більше з бізнес-логіки причин; наприклад, щоб заборонити Delete, це може бути, що це не дозволяє "видалити" цей конкретний ресурс після його створення. Я зазвичай розглядаю назву ресурсу, розглядаючи всі дієслова CURD, щоб допомогти зробити вибір дизайну.
додано Автор Ming Chan, джерело

Учасник має статус Active і Disabled

Таким чином, статус є власністю суб'єкта/ресурсу-члена; у цьому випадку, чому ви не хочете використовувати просто метод PUT на ресурсі Member зі статусом Disabled?

0
додано
Член має багато інших полів, які клієнти можуть захотіти оновити. Вони використовують поставлені в цій ситуації. Ці оновлення зазвичай не призводять до запуску інших робочих процесів. Вони є простими оновленнями для нашого сховища даних. Але відключення члена є складним робочим процесом і тому його необхідно відокремити від оновлення учасників як концепцію.
додано Автор Suhas, джерело
Ви маєте на увазі рядок запиту? Я сумніваюся, що я б використовував рядки запитів на пошті, щоб відправити параметри. І один пост, щоб керувати ними все виглядає як порушення SRP для мене.
додано Автор Suhas, джерело
у вас є ресурс під елементами/{someId}. Використовуйте GET для отримання цього ресурсу, DELETE - для видалення цих ресурсів, PUT - для оновлення цих ресурсів. Метод POST є безкоштовним, тому ви можете використовувати його, щоб активувати деактивацію вашого члена
додано Автор maks, джерело
якщо у вас є кілька випадків запуску процесу робочого процесу, які можна ідентифікувати за різними параметрами методом POST
додано Автор maks, джерело

Учасник має статус Active і Disabled

Таким чином, статус є власністю суб'єкта/ресурсу-члена; у цьому випадку, чому ви не хочете використовувати просто метод PUT на ресурсі Member зі статусом Disabled?

0
додано
Член має багато інших полів, які клієнти можуть захотіти оновити. Вони використовують поставлені в цій ситуації. Ці оновлення зазвичай не призводять до запуску інших робочих процесів. Вони є простими оновленнями для нашого сховища даних. Але відключення члена є складним робочим процесом і тому його необхідно відокремити від оновлення учасників як концепцію.
додано Автор Suhas, джерело
Ви маєте на увазі рядок запиту? Я сумніваюся, що я б використовував рядки запитів на пошті, щоб відправити параметри. І один пост, щоб керувати ними все виглядає як порушення SRP для мене.
додано Автор Suhas, джерело
у вас є ресурс під елементами/{someId}. Використовуйте GET для отримання цього ресурсу, DELETE - для видалення цих ресурсів, PUT - для оновлення цих ресурсів. Метод POST є безкоштовним, тому ви можете використовувати його, щоб активувати деактивацію вашого члена
додано Автор maks, джерело
якщо у вас є кілька випадків запуску процесу робочого процесу, які можна ідентифікувати за різними параметрами методом POST
додано Автор maks, джерело

Якщо вимкнути користувача, то чому б не використовувати HTTP PATCH?

Дивіться цю відповідь на подібне запитання

0
додано
Я додав деталі до запитань. Вимкнення користувача не є простим оновленням.
додано Автор Suhas, джерело