Якщо операція RESTful 'PUT' щось поверне


437

Мені було цікаво, що думка людей стосується PUTоперації RESTful, яка нічого не повертає (нульового) в тілі відповідей.

Відповіді:


615

Специфікація HTTP ( RFC 2616 ) містить ряд рекомендацій, що застосовуються. Ось моя інтерпретація:

  • Код статусу HTTP 200 OKдля успішного PUT оновлення наявного ресурсу. Орган з реагуванням не потрібен. (Відповідно до розділу 9.6 , 204 No Contentце навіть більше.)
  • Код статусу HTTP 201 Createdдля успішного PUT нового ресурсу з найбільш специфічним URI для нового ресурсу, що повертається у полі заголовка Location та будь-якими іншими відповідними URI та метаданими ресурсу, відлунюваних у тілі відповіді. ( Розділ 10.2.2 RFC 2616 )
  • Код статусу HTTP 409 Conflictдля PUT, який невдалий через модифікацію третьої сторони, зі списком відмінностей між спробою оновлення та поточним ресурсом в тілі відповіді. ( RFC 2616 Розділ 10.4.10 )
  • Код статусу HTTP 400 Bad Requestдля невдалого PUT з текстом на природній мові (наприклад, англійською) в органі відповіді, який пояснює, чому PUT не вдалося. ( RFC 2616 Розділ 10.4 )

25
@stian Цікаво! Це здається досить самонадійним з боку Mozilla, оскільки я не можу знайти нічого в RFC 2616 (зокрема, розділи 10.2 Успішно 2xx та 10.2.1 200 ОК ), які конкретно виключають використання 200PUT, DELETE або будь-якого іншого методу. Я щось пропустив? Такі як Mozilla, що стає босом W3 та IETF? ;) Або, можливо, вони просто ніколи не чули про принцип стійкості Постеля.
система ПАУЗА

52
@stian: Цей вирок було знято 3 лютого 2013 року. Мабуть, тому, що хтось читав про це тут. ;) developer.mozilla.org/en-US/docs/HTTP/…
Крістіан Стремпфер

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

8
@systemPAUSE Приємна відповідь. Один невеликий момент: якщо ви не збираєтеся повертати орган реагування на успішну операцію, я б запропонував використовувати виключно номер 204. Деякі клієнти (наприклад, jQuery Ajax) задихнуться, якщо вони очікують відповіді, що не має нульової довжини, але не отримають її. Приклад цього можна побачити в цьому запитанні .
nick_w

3
Можливо, RFC2616 було оновлено з моменту відповіді на це. Ні де в 9.6 це не згадується No response body neededстосовно 200. Насправді орган реагування взагалі не згадується стосовно PUT. У ньому зазначено лишеIf an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
Джеймс

164

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

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


3
"сервер також може застосувати деяку обробку до цього ресурсу": я це новий. Це справді ВІДПОВІДНО?
Raedwald

22
@Raedwald впевнений, що так. REST не вимагає оновлення всього ресурсу на PUT, хоча це, як правило, рекомендується. Деякі поля, можливо, не мають сенсу оновлювати - наприклад, створена дата або остання змінена дата, наприклад, ймовірно, не повинні бути включені до тіла PUT, але, ймовірно, будуть змінені в результаті PUT. Коли вже було сказано, я не погоджуюся з LiorH, що PUT повинен призвести до повернення ресурсу; Я зажадаю GET після PUT, щоб отримати оновлений ресурс.
Рандольфо

19
@ Randolpho REST не вимагає, щоб весь ресурс оновлювався в режимі PUT, чи не так це PATCH?
Marco Ciambrone

14
@MarcoCiambrone Так, я погоджуюсь, і я повторюю свій попередній коментар. Я змінив мелодію на REST і PUT - PUT завжди повинен бути безсильним і ніколи не повинен використовуватися для часткового оновлення. POST є єдиною альтернативою, якщо PATCH не підтримується, і в цьому випадку PATCH може бути хорошою альтернативою. PATCH, однак, є новим дієсловом і може не підтримуватися деякими серверними рамками.
Рандольфо

2
Відповідь була написана задовго до rfc7231, але в розділі 4.3.4 з'ясовано "Метод PUT вимагає, щоб стан цільового ресурсу було створено або замінено станом, визначеним представленням, доданим до корисного навантаження повідомлення запиту"
aaaaaa

3

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

Якщо я просто приймаю PUT і не маю нічого доповідати, я використовую код статусу 204 без тіла. Якщо я маю щось повідомити, я використовую код статусу 200 і включаю тіло.


2

Специфікація HTTP / 1.1 (розділ 9.6) обговорює відповідні коди відповідей / помилок. Однак він не стосується вмісту відповіді.

Що б ви очікували? Простий код відповіді HTTP (200 тощо) здається мені простим і однозначним.


Так, але що робити, якщо ви хочете перевірити, чи вставлені дані в db після PUT або POST дійсно представляють потрібні справжні дані. Було б краще, якщо HTTP може переслати тіло відповіді.
tnkh

1
@tnkh, що ви пропонуєте, це просто жахлива ідея. Зробіть окремий дзвінок GET після успішного оновлення, щоб досягти бажаного. Для забезпечення ефективності введіть шар кешування, якщо у вас виникли проблеми в цьому відділі. Ми не можемо вирішити ці питання, возившись з логікою "все йде". Не заплутайтеся з «твердими» та основними принципами програмування, які мають бути здоровими у 2020 році. Це ганьба!
XDS

@XDS Я визнаю вашу першу частину коментаря. Але не можу перестати закочувати очі після цього. Веселий коментар
tnkh

Дякуємо, що розробимо питання, чому ви вважаєте, що це смішно.
XDS

2

Якщо резервним інтерфейсом API REST є реляційна база даних SQL, то

  1. ви повинні мати RowVersion у кожному записі, який можна оновити (щоб уникнути втраченої проблеми оновлення )
  2. Ви завжди повинні повертати нову копію запису після PUT (щоб отримати новий RowVersion ).

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


1

Код відповіді Http 201 для "Створено" разом із заголовком "Місцезнаходження", щоб вказати, де клієнт може знайти щойно створений ресурс.


5
Об'єкти PUT не є (або не повинні бути) новоствореними ресурсами
kdazzle

9
@kdazzle PUT, безумовно, може бути новоствореним ресурсом, і часто це було б. w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6
Charlie Schliesser

3
Просто для пояснення мого коментаря трохи краще. PUT означає, що поставте цей елемент у вказане місце, замінивши те, що зараз там (якщо це можливо).
користувач1751825

3
Правильно, "заміна того, що зараз є" є ключовою фразою. Вона вже повинна існувати і її замінюють. PUT не повинен створювати нові ресурси.
Кевін М

3
@KevinM Як і в останньому документі RFC doc rfc7231 , він говорить про те, що ресурси можна створити: "Метод PUT вимагає створити або замінити стан цільового ресурсу [...]", і причину, по якій ви думаєте, PUT не може створити новий ресурс, тому що ви не обов'язково знаєте місце розташування нового ресурсу. Але якщо ви знаєте його місцезнаходження / ідентифікатор, його можна створити, якщо його ще немає.
Лео Лей

0

Я використовував RESTful API у своїх службах, і ось моя думка: Спочатку ми повинні дійти до загального вигляду: PUTвикористовується для оновлення ресурсу, який не створює та не отримує.

Я визначив ресурси за допомогою: Stateless resourceі Stateful resource:

  • Ресурси без громадянства Для цих ресурсів достатньо повернути HttpCode з порожнім тілом, досить.

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

Але , для служби або системи, зберегти йогоsimple,clearly,easy to use and maintainце найголовніше.


6
"PUT використовується для оновлення ресурсу, який не створюється та не отримує." - це не вірно, ані звичайно. За специфікацією, PUT може створити ресурс. Очистити = дотримуючись загальновідомої специфікації.
Імре Пювель

-3

Так само, як порожній орган запиту відповідає початковій меті запиту GET, а порожній орган відповіді відповідає початковій меті запиту PUT.


-3

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

редагувати: я розмірковував відповідно до цілісності даних та / або зберігання записів; метадані, такі як хеш MD5 або мітка часу за отриманий час, можуть бути корисними для великих файлів даних.


1
Як щодо 200 ОК у заголовку відповіді про стан? Ви думаєте, що хотілося б сказати: "Добре працювали дякую?"
AnthonyWJones

заголовок відповіді міститиме код статусу, і так, ми говоримо про HTTP в цей момент :)
AwkwardCoder

-4

В ідеалі це призведе до успішної / невдалої відповіді.


13
Не в тілі, що реагує. Код статусу HTTP - це місце для цього. Можливо, якщо є помилка, якась розширена інформація про помилку може бути повернута у відповіді:
Павло

-4

Існує різниця між заголовком і тілом HTTP-відповіді. PUT ніколи не повинен повертати тіло, але повинен повертати код відповіді у заголовку. Просто виберіть 200, якщо це було успішно, і 4xx якщо ні. Немає такого поняття, як нульовий код повернення. Чому ти хочеш це робити?

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