Видалення ресурсу за допомогою http DELETE


123

Отже, враховуючи, що дієслово DELETE в Http є idempotent, коли я видаю наступний запит, що має відбутися другий (або третій, або четвертий, і т. Д.)?

DELETE /person/123

Перший раз ресурс видаляється, і я повертаю 204 (успішно, без вмісту). Чи варто повернути 204 при наступних дзвінках або 404 (не знайдено)?

Відповіді:


153

Оскільки HTTP-запити в системі без стану повинні бути незалежними, результати одного запиту не повинні залежати від попереднього запиту. Поміркуйте, що має статися, якщо два користувачі зробили ВІДОМЛЕННЯ на одному ресурсі одночасно. Для другого запиту має сенс отримати 404. Це ж має бути справедливим, якщо один користувач робить два запити.

Я здогадуюсь, що отримання DELETE повернення двох різних відповідей не вважає вас безсильним. Мені здається корисним вважати ідентичні запити як залишення системи в одному стані, не обов'язково мати однакову відповідь. Отже, незалежно від того, ви видалите наявний ресурс чи намагаєтесь ВИДАЛИТИ ресурс, який не існує, стан ресурсу сервера такий же.


4
Дякую. Це має багато сенсу. Я справді думав про безсилля як про те, що повертає ту саму відповідь.
Крейг Вілсон

4
@Craig Обережно! У кулінарній книзі Subbu повністю суперечить тому, що я щойно сказав. За його словами, idempotency означає, що він повинен повернути ту саму відповідь. На щастя, Subbu буде на RESTFest, тому я збираюся уточнити з ним там.
Даррел Міллер

57
Якщо ВИДАЛИТИ щось, чого не існує, вам слід просто повернути 204 (навіть якщо ресурсу ніколи не було). Клієнт хотів, щоб ресурс пішов, і його немає. Повернення 404 виявляє внутрішню обробку, яка не є важливою для клієнта, і призведе до непотрібної умови помилки.
Брайан

9
@DarrelMiller Я думаю, що ключова концепція тут полягає в тому, що ви не повинні використовувати DELETE для перевірки наявності ресурсу, ви спершу використовуєте GET для цього. Тоді, якщо відповідь 200, ви виконаєте DELETE; інакше навіть не намагайся це робити. Тому я думаю, що є сенс завжди повертати 204 на DELETE.
manei_cc

10
@Brian В RFC кажуть, що слід поводитись так rm. rmповертає помилку, якщо її не існує. tools.ietf.org/html/rfc7231#section-4.3.5
Dax

32

Кулінарна книга RESTful веб-служб - чудовий ресурс для цього. Випадково його попередній перегляд google показує сторінку про DELETE (сторінка 11):

Метод DELETE ідентичний. Це означає, що сервер повинен повернути код відповіді 200 (ОК), навіть якщо сервер видалив ресурс у попередньому запиті. Але на практиці реалізація DELETE як ідентичної операції вимагає від сервера відстежувати всі видалені ресурси. В іншому випадку він може повернути 404 (Не знайдено).


Так, це виглядає як чудовий ресурс. Однак розділ DELETE не підтягується для мене (це сторінка 23, а попередній перегляд відредаговано). Ви читали цю книгу? Чи трапляється вам знати відповідь на моє запитання?
Крейг Вілсон

Ця книга є обов'язковою для побудови REST (вона розмовляє, зокрема, не мовою).
yves amsellem

7
@Craig Читаючи кулінарну книгу, вона говорить, що ви ДОЛЖНІ повернути 200 ОК, навіть якщо ви її вже видалили. Однак на практиці, яка вимагатиме від сервера відстежувати всі видалені ресурси, отже, МОЖЕТЕ використовувати 404. Продовжує говорити, що проблеми безпеки можуть вимагати від вас завжди повертати 404. Сторінка 11.
Даррел Міллер

+1 По-друге, і дуже рекомендую книгу для розробки послуг RESTful.
Paul DelRe

18
Що ж, книга неправильна. Idempotency не означає, що код статусу буде однаковим. Важливим є кінцевий стан сервера.
Джуліан Решке

13

Я погоджуюсь з тим, що сказана поточна обрана відповідь, що 2-й (і 3-й, 4-й, ...) DELETE повинен отримати 404 . І я помітив, що відповідь має 143 голоси, але також є протилежний коментар, який має 54 голоси, тому громада розділена на 2 табори приблизно у співвідношенні 3: 1. Ось більше інформації для врегулювання цієї тривалої дискусії.

  1. Перш за все, давайте НЕ почнемо з того, що "я" думаю, що "ти" думаєш, або що ще думає інший автор книги. Почнемо з специфікацій HTTP, тобто RFC 7231.

    • RFC 7231, розділ 4.3.5 DELETE, коли згадується лише про успішну відповідь, має бути 2xx, але не зазначає, що отримає наступний DELETE. Тож давайте копаємо глибше.
    • RFC 7231, розділ 6.5.4 404 Не знайдено, каже, що відповідь 404 для ресурсу не існує. Оскільки жоден конкретний метод http (зокрема, не DELETE) не викликав би поводження з іншим способом, ми можемо інтуїтивно скластись враження (і це справедливо), що мій запит DELETE /some/resource/which/does/not/existповинен призвести до 404. Потім, DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/agoможливо, також повернеться 404 Тоді, чому має DELETE /some/resource/i/deleted/five/seconds/agoбути інакше? "Але як щодо ідентичності ?!", я чую, що ти це кричиш. Почекай, ми ось-ось вберемося в це.
    • Історично, RFC 2616, опублікований у 1999 році, був найбільш посиланням специфікацій HTTP 1.1. На жаль, його опис про ідентифікацію було невиразним , що залишає місце для всіх цих дискусій. Але ці характеристики були замінені RFC 7231. Цитується з RFC 7231, розділ 4.2.2 Ідентифіковані методи , акцент мій:

      Метод запиту вважається "idempotent", якщо призначений ЕФЕКТ НА СЕРВЕРІ декількох однакових запитів із цим методом такий же, як ефект для одного такого запиту. З методів запиту, визначених цією специфікацією, PUT, DELETE та безпечні методи запиту є ідентичними .

      Отже, написано в специфікаціях, idempotency - це все про вплив на сервер. Перший DELETE, що повертає 204, а потім наступний DELETE, що повертається 404, такий різний код статусу НЕ робить DELETE неідентичним. Використовувати цей аргумент для обгрунтування наступного повернення 204, просто не має значення.

  2. Гаразд, тому мова не йде про ідентифікацію. Але тоді може бути наступне питання, що робити, якщо ми все-таки вирішимо використати 204 в наступному DELETE? Чи гаразд?

    Гарне питання. Мотивація зрозуміла: дозволити клієнтові все-таки досягти наміченого результату, не турбуючись про обробку помилок. Я б сказав, що повернення 204 в наступному DELETE - це в основному нешкідливий "біла брехня" на стороні сервера, яка на стороні клієнта не одразу скаже різницю. Ось чому є близько 25% людей, які роблять це в дикій природі, і це, здається, все ще працює. Тільки майте на увазі, що таку брехню можна вважати семантично дивною, оскільки GET /non-existповертає 404, але DELETE /non-existдає 204, тоді клієнт зрозуміє, що ваша послуга не відповідає повністю розділу 6.5.4 404 Не знайдено .

    Але я хочу зазначити, що намічений шлях, натяканий RFC 7231, тобто повернення 404 на наступному DELETE, не повинен бути проблемою в першу чергу. 3 рази більше розробників вирішили це зробити, і чи чули ви коли-небудь великий інцидент або скаргу, викликану тим, що клієнт не може впоратися з 404? Імовірно, ні, і це тому, що будь-який порядний клієнт, який реалізує HTTP DELETE (або будь-який метод HTTP, з цього приводу), не сліпо вважатиме, що результат завжди буде успішним 2xx. І тоді, як тільки розробник почне розглядати питання про помилки, 404 Not Found була б однією з перших помилок, яка виникає на увазі. У цей момент він / вона, мабуть, зробить висновок, що ігнорувати помилку 404 для операції HTTP DELETE семантично безпечно. І вони так зробили.

Проблема вирішена.


2
+1 "idempotency - це все про вплив на сервер". Прискіпливо відповів. Молодці! Я віруюча 404 для наступних DELETE запитів.
nwayve

11

Перша ВИДАЛЕННЯ : 200 або 204.

Подальші ВИДАЛЕННЯ : 200 або 204.

Обґрунтування : DELETE має бути безвідмовним. Якщо ви повернете 404 на другій DELETE, ваша відповідь змінюється від коду успіху до коду помилки . Клієнтська програма може вчинити неправильні дії, виходячи з припущення, що ВИДАЛИТИ не вдалося.

Приклад :

  • Припустимо, що операція DELETE є частиною багатокрокової операції (або "саги"), виконаної клієнтською програмою.
  • Клієнтська програма може бути, наприклад, мобільним додатком, який виконує банківські транзакції.
  • Скажімо, у клієнтської програми є автоматичний повтор для повторної операції DELETE (це має сенс, оскільки DELETE повинен бути безвідмовним).
  • Скажімо, перший DELETE був успішно виконаний, але 200 відповідей втратили на шляху до клієнтської програми.
  • Клієнтська програма повторить DELETE.
  • Якщо друга спроба повертає 404, клієнтська програма може скасувати загальну операцію через цей код помилки.
  • Але оскільки перший DELETE успішно виконаний на сервері, система може залишитись у непослідовному стані .
  • Якщо друга спроба поверне 200 або 204, клієнтська програма буде тривати, як очікувалося.

Щойно для ілюстрації використання цього підходу, посібник із стилів HTTP API для PayPal має таке керівництво:

DELETE: Цей метод ДОЛЖЕН би повернути код статусу 204, оскільки немає необхідності повертати будь-який вміст у більшості випадків, оскільки запит - це видалити ресурс, і він був успішно видалений.

Оскільки метод DELETE ОБОВ'ЯЗКОВО повинен бути ідентичним, він ДОСЛІДНО повертати 204, навіть якщо ресурс уже видалений. Зазвичай споживача API не хвилює, чи був видалений ресурс у рамках цієї операції чи раніше. Це також причина того, що 204 замість 404 слід повернути.


1
Питання в тому, що важливо для клієнта, що він видалив ресурс, або що ресурс був видалений. Що робити, якщо якийсь інший клієнт видалив ресурс під час саги. Ви дійсно хочете провалитись, враховуючи, що досягнута мета клієнтів?
Даррел Міллер

1
@DarrelMiller Добре. Що важливіше залежить від контексту бізнесу. Але в цілому я вважаю за краще повернути 204 з другої спроби DELETE, навіть якщо ресурс був видалений іншим клієнтом. Я не хочу, щоб послуга вийшла з ладу (тобто 404), враховуючи, що мета клієнтів була досягнута.
Пауло Мерсон

2
Як згадували інші, idempotency - це не те, що ваш код відповіді, це те, що стан вашого сервера.
Ніранджан

@Niranjan Я погоджуюся, що idempotency стосується стану сервера, але інший код відповіді може змусити клієнта змінити стан сервера без потреби, скасувавши поточну сагу.
Пауло Мерсон

@Paulo Merson, який код ви повернете, якщо клієнт попросить видалити елемент, який НІКОЛИ не існував? 204? або 404? Якщо ви завжди повертаєте 204, який сенс перевіряти код повернення?
frenchone
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.