Чи REST DELETE справді ідентичний?


165

DELETE повинен бути безсильним.

Якщо я ВИДАЛУЮ http://example.com/account/123, він видалить обліковий запис.

Якщо я знов це зроблю, чи сподіваюся на 404, оскільки облікового запису більше не існує? Що робити, якщо я спробую ВІДКРИТИ обліковий запис, який ніколи не існував?


11
На додаток до відповідей, я б пропонував не зосереджуватись занадто сильно на ідентичній властивості загалом: це нічого не говорить про комутаційність та паралельні запити. Наприклад, N + 1 одного і того ж запиту PUT "R1" повинен мати той самий ефект, але ви не знаєте, чи інший клієнт зробив інший запит PUT / DELETE "R2" між вашими, так що n R1 = R1 і m R2 = R2, якщо ви отримуєте переплетені "R1" та "R2" запити, не обов'язково "виглядатимуть" ідентично, якщо ви берете лише один клієнт.
Бруно

Відповіді:


188

Idempotence посилається на стан системи після завершення запиту


У всіх випадках (окрім проблем з помилками - див. Нижче) облікового запису більше не існує.

від сюди

"Методи також можуть мати властивість" idempotence ", оскільки ( окрім помилок чи проблем із закінченням терміну ) побічні ефекти N> 0 однакових запитів такі ж, як і для одного запиту. Методи GET, HEAD, PUT і DELETE діляться ця властивість. Крім того, методи ВАРІАНТИ та СЛІД НЕ повинні мати побічних ефектів, і вони по суті є ідентичними ".


Ключовий біт там є побічними ефектами N> 0 однакових запитів такий же, як і для одного запиту.

Було б правильно вважати, що код статусу буде іншим, але це не впливає на основну концепцію idempotency - ви можете надсилати запит не один раз без додаткових змін до стану сервера.


3
Побічні ефекти! == стан сервера
wprl

2
@wprl Йде дискусія щодо того, що насправді є цим "побічним ефектом". Це може бути "стан сервера" або це відповідь, що надсилається клієнту. leedavis81.github.io/is-a-http-delete-requests-idempotent
Аліреза

Ось аргумент, що 404 на другому DELETE може фактично змінити стан сервера: stackoverflow.com/a/45194747/317522
Пауло Мерсон

1
@PauloMerson Дякую, особисто я не думаю, що це має значення, чи буде друге повернення 404 чи 200, стан сервера не змінився, тому я задоволений цим.
Кріс Маккаулі

46

Idempotent стосується ефекту запиту, а не коду відповіді, який ви отримуєте.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2 говорить:

Методи також можуть мати властивість "idempotence", оскільки (окрім помилок чи проблем із закінченням терміну) побічні ефекти N> 0 однакових запитів такі ж, як і для одного запиту.

Хоча ви можете отримати інший код відповіді, ефект надсилання N + 1 DELETE запитів на один і той же ресурс можна вважати однаковим.


13

Важлива відмінність полягає в тому, що імедпотент відноситься до побічних ефектів , а не до всіх ефектів чи реакцій. Якщо це зробити, DELETE http://example.com/account/123то ефект полягає в тому, що обліковий запис 123 зараз видалено з сервера. Це єдиний ефект, єдиний і зміна стану сервера. Тепер скажемо, що ви повторите той самий DELETE http://example.com/account/123запит, сервер відповість по-різному, але його стан той же.

Це не так, як запит DELETE вирішив змінити стан сервера по-іншому, тому що обліковий запис відсутній, наприклад, видалення іншого облікового запису або залишення журналу помилок. Так, ви можете викликати один і той же запит DELETE мільйон разів, і ви можете бути впевнені, що сервер знаходиться в такому ж стані, як і вперше .


7

Від HTTP RFC :

Методи також можуть мати властивість "idempotence", оскільки (окрім помилок чи проблем із закінченням терміну) побічні ефекти N> 0 однакових запитів такі ж, як і для одного запиту.

Зауважте, що це "побічні ефекти", а не "відповідь".


7

Так. Незалежно від коду відповіді.

З останнього RFC для HTTP 1.1 (міна акценту):

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

У ньому прямо написано, що відповідь може відрізнятися. Що ще важливіше, воно вказує на причину концепції: якщо дія є ідентичною, клієнт може повторити дію, коли зіткнеться з будь-якою помилкою, і знає, що цим нічого не зламає; якщо ні, то клієнту доведеться зробити додатковий запит (можливо GET), щоб перевірити, чи ефективний попередній, перш ніж він безпечно повторить дію. Поки сервер може надати таку гарантію, дія є безсумнівною. Цитата з іншого коментаря :

Обчислювальна імпотенція стосується надійності системи. Оскільки речі можуть вийти з ладу (наприклад, відключення мережі), як виявити несправність, як відновитись? Найпростіше відновлення - це просто зробити це знову, але це працює лише тоді, коли це робиться повторно. Напр. discard(x), Ідентичний, але pop()ні. Вся справа у відновленні помилок.


2

Я думаю, те саме, 404 - Рахунок не існує.

Ви можете заперечити 400 - поганий запит. Але в сенсі REST об'єкт, на який ви просили виконати дію, не існує. Це означає 404.


1
Щоб створити 400, ви повинні знати, що раніше існував об'єкт, який дуже неспокійний.
annakata

1
@annakata, 400 навіть не для ресурсів, які існували (можливо, ви маєте на увазі 410 / Зникли), це для поганих запитів "Запит не міг зрозуміти сервер через неправильний синтаксис".
Бруно

3
@Bruno - Я знаю, що це означає, ОП цитувало це.
annakata

1
Я думаю, що 200 було б добре. Ви хочете, щоб стан сервера був таким, що облікового запису немає. Чи має значення, який запит насправді змусив його піти? На другий запит все ще немає, стан сервера не змінився.
Енді

1

Цитується з моєї іншої відповіді тут :

Історично, RFC 2616, опублікований у 1999 році, був найбільш посиланням специфікацій HTTP 1.1. На жаль, його опис про ідентифікацію було невиразним , що залишає місце для всіх цих дискусій. Але ці характеристики були замінені RFC 7231. Цитується з RFC 7231, розділ 4.2.2 Ідентифіковані методи , акцент мій:

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

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


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

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

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

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