використовує PUT з бічними впливами прийнятними (REST)


9

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

Чи допустимо тут використовувати PUT? Чи є кращі альтернативи?

PUT /person/F02E395A235

{
   time: 1234567,
   fields: {
      name: 'John',
      age: '41'
   }
}

На сервері

doPut('person/:personId',
   // create a new person snapshot
)

Редагувати:

Користувач буде видимий для історії, якщо виклик кілька разів призведе до декількох версій.

Рішенням було перевірити, чи унікальна версія перед тим, як створити її.

Відповіді:


11

Люди, які розробляли HTTP / 2, були набагато більш детальними щодо своїх уявлень про те, що HTTP повинен робити, зберігаючи старе значення. Давайте подивимось, що специфікація проекту HTTP / 2 має сказати про ідентифікацію:

4.2.2. Ідентичні методи

Метод запиту вважається "idempotent", якщо призначений ефект на сервері декількох однакових запитів із цим методом такий же, як ефект для одного такого запиту. Якщо методи запиту визначені цією специфікацією, PUT, DELETE та безпечний запит методи ідентичні.

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

Запропонований ефект на сервері для кожного такого запиту PUT полягає в оновленні ресурсу, ідентифікованого цим URI . Це саме те, що відбувається у вашому випадку.

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


Ваша редакція:

Користувач буде видимий для історії, якщо виклик кілька разів спричинить за собою кілька перетворень

Що стосується ресурсу, це не є побічним ефектом . Ресурс цього URI не змінюється (ті ж властивості отримують PUT). Історія - це лише метадані, оскільки це, ймовірно, запитується іншим URI або з різними заголовками запитів.


Виключено, тому що ви відповідаєте на мою конкретну проблему: "чи прийнятно PUT створювати видиму для користувача історію", і дайте мені рішення, дякую
roo2

До якої проблеми це рішення? Що timeвласність оновлюється? Я думаю, що це і метадані, хоча вони є в ресурсі.
CodeCaster

1
Проблема полягала в тому, що якщо було надіслано декілька PUT, користувач отримає довгу історію скасування з надмірною інформацією. перевірка унікальності вирішує, що
roo2

12

HTTP розрізняє два властивості:

  • Ідентифікація
  • Безпека

Ідентифікація визначається специфікацією так:

Методи також можуть мати властивість " idempotence ", оскільки (окрім помилок чи проблем із закінченням терміну дії) побічні ефекти N> 0 однакових запитів такі самі, як і для одного запиту. Методи GET, HEAD, PUTі DELETEволодіють цією властивістю. Крім того , методи OPTIONSі TRACE НЕ ПОВИННО мати побічні ефекти, і тому по своїй суті ідемпотентна.

І безпека:

Зокрема, було встановлено конвенцію про те, що методи GETта HEADметоди НЕ повинні мати значення для вжиття інших дій, ніж пошук. Ці методи слід вважати " безпечними ". Це дозволяє агентам користувача представляти інші методи, такі як POST, PUTі DELETE, особливим чином, щоб користувач ознайомився з тим, що вимагається можлива небезпечна дія.

Природно, неможливо забезпечити, щоб сервер не генерував побічні ефекти в результаті виконання GETзапиту; насправді деякі динамічні ресурси вважають цю особливість. Тут важливим є те, що користувач не вимагав побічних ефектів, тому не може нести за них відповідальність.

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

Це розподіляє методи на три категорії:

  • сейф (і , отже , також ідемпотентна) GET, HEAD, OPTION,TRACE
  • ідемпотентів але не завжди безпечно: PUT,DELETE
  • ні безпосереднім, ні безпечним: POST

PUT не повинен мати побічних ефектів.

Це неправильно. PUTє безсильним, але не безпечним. Весь сенс в PUTце мати побічний ефект, а саме оновлення ресурсу. Що означає idempotency, це те, що оновлення одного і того ж ресурсу з тим самим вмістом кілька разів повинно мати такий же ефект, як оновлення його лише один раз.

Зверніть увагу на останній абзац у розділі про безпеку [наголос міни]:

Природно, неможливо забезпечити, щоб сервер не генерував побічні ефекти в результаті виконання GETзапиту; насправді деякі динамічні ресурси вважають цю особливість. Тут важливим є те, що користувач не вимагав побічних ефектів, тому не може нести за них відповідальність .

Хоча це речення говорить про GETбезпеку та безпеку, ми можемо припустити, що автори також мали на меті застосувати ті ж міркування PUTта ідентичність. IOW: PUTповинен мати лише один видимий для користувача побічний ефект, а саме оновлення названого ресурсу. У нього можуть бути й інші побічні ефекти, але користувач не може нести за них відповідальність.

Наприклад, той факт, що PUTє ідентичним, означає, що я можу повторювати його так часто, як мені хочеться: специфікація гарантує, що його виконання кілька разів буде точно таким же, як його виконати один раз. Цілком справедливо створити відставання старих версій як побічний ефект цих кількох PUTзапитів. Однак, якщо в результаті багаторазових повторних робіт ваша база даних заповнить відсталі старі версії, це не моя проблема, це ваша.

IOW: вам дозволяється мати стільки побічних ефектів, скільки ви хочете, але

  1. він повинен виглядати перед користувачем так, ніби їхні запити ідентичні
  2. ви відповідаєте за ці побічні ефекти, а не за користувача

Так, idempotency - це про стан введеного ресурсу, а не про будь-який інший стан сервера / послуги, на який впливає акт PUT.
Мар'ян Венема

Оновлення за велике пояснення безпеки та
безвідмовності

Чудове пояснення. Однак ви робите кілька таких тверджень: "Вся суть PUT - це побічний ефект, а саме оновлення ресурсу". Це здається протиріччям, якщо ви не маєте на увазі щось інше під терміном "побічний ефект", ніж "щось вторинне або ненавмисне, що відбувається на додаток до первинного, призначеного ефекту".
MarredCheese

@MarredCheese: Я використовую термін у його стандартному значенні програмування, що в основному означає "будь-який" результат ", який не є зворотним значенням".
Jörg W

Ах, звичайно. Дякуємо за роз’яснення.
MarredCheese

1

Ви вірні, що PUT не повинен мати жодних побічних ефектів , однак я б до цього щось додав.

PUT не повинен побічно впливати на ресурс, для якого виконується операція PUT

Ви оновлюєте personресурс, ідентифікований як F02E395A235, тому використання PUT є правильним. Тепер, як правило бізнесу, ви також відстежуєте зміни, які невидимі для виклику (споживача послуги REST). Це не додасть новий елемент у personресурс. Історичний знімок не буде доступний за допомогою /person/кінцевої точки. Тому я вважаю, що PUT має бути цілком прийнятним у цьому випадку.


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