Чи нормально REST повертати вміст після POST?


88

Я використовую RESTlet і створив ресурс. Я обробляю POST методом заміщення acceptRepresentation.

Клієнт повинен надіслати мені деякі дані, потім я зберігаю їх у БД, встановлюю відповідь 201 (SUCCESS_CREATED), і мені потрібно повернути деякі дані клієнту, але тип повернення acceptRepresentationє void.

У моєму випадку мені потрібно повернути якийсь ідентифікатор, щоб клієнт міг отримати доступ до цього ресурсу.

Наприклад, якщо у мене був ресурс з URL-адресою, /resourceі клієнт надсилає запит POST, я додаю новий рядок у БД і його адреса повинна бути /resource/{id}. Мені потрібно відправити {id}.

Я щось роблю не так? Чи дозволяють принципи REST повернути щось після POST? Якщо так, то як я можу це зробити, і якщо ні, то який спосіб вирішити цю ситуацію?


Див. Відповідь Тома, як встановити тіло відповіді зсередини acceptRepresentation ().
Avi Flax

Відповіді:


96

REST просто говорить, що ви повинні відповідати єдиному інтерфейсу. Іншими словами, там сказано, що ви повинні робити те, що повинен робити POST відповідно до специфікації HTTP . Ось цитата з цієї специфікації, яка є релевантною,

Якщо на вихідному сервері було створено ресурс, відповідь ПОВИНЕН бути 201 (Створений) і містити сутність, яка описує стан запиту та посилається на новий ресурс, та заголовок Location (див. Розділ 14.30).

Як видно з цього, у вас є два місця, де ви можете вказати клієнту, де знаходиться новостворений ресурс. Заголовок Location повинен мати URL-адресу, яка вказує на новий ресурс, і ви також можете повернути сутність із деталями.

Я не впевнений, у чому різниця між перевизначенням acceptRepresentation () та перевизначенням post (), але цей приклад показує, як повернути відповідь з POST.


2
@ del-boy: Дивіться відповідь Тома, як встановити тіло відповіді зсередини acceptRepresentation ().
Avi Flax

1
Цитата специфікації HTTP не забороняє відповіді, якщо ви подивитесь на Розділ 6, це ясно: це дозволено: Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or response status code. An entity consists of entity-header fields and an entity-body, although some responses will only include the entity-headers.
MikeF

@MikeF Я не мав наміру робити висновок, що тіло відповіді не було дозволено. Частина специфікації, яку я цитував, конкретно говорить "і містити сутність". Я повинен був бути чіткішим у своєму тексті.
Даррел Міллер,

16

Я б відмовився надсилати що-небудь у тілі відповіді. Просто встановіть для Location: (повну) URL-адресу новоствореного ресурсу.

Ваш опис свідчить про те, що це саме така семантика:

  1. Опублікуйте щось, щоб створити його
  2. Відповідь достатньо, щоб знати дві речі:
    1. Що сталося творіння (201)
    2. Де знайти нову річ (заголовок Location)

Все інше зайве.


Не те, що Вікіпедія завжди є хорошим джерелом, але в цьому також стверджується, що [[]] Надати інформацію про місцезнаходження новоствореного ресурсу. У цьому випадку заголовок Location повинен надсилатися із кодом статусу HTTP 201 або 202 . "
Арджан

1
POST може виконувати логіку, яка створює один або кілька ресурсів. Результат обробки може знадобитися клієнту. Отже, повернення його у відповідь дозволяє уникнути необхідності робити один або кілька викликів GET до API. Дані, створені / змінені методом POST, можуть не бути (і часто не є) зайвими для клієнта.
Паулу Мерсон

10

Два різні запитання:

Чи підтримує шаблон програми REST повернення даних у POST?

Я не думаю, що REST явно забороняє це, але бажаний спосіб лікування прописаний у відповіді Даррела.

Чи дозволяє рамка RESTlet повернення даних у POST?

Так, навіть якщо воно повертає void, у класі, що розширює Resource, ви маєте повний доступ до об'єкта Response за допомогою методу getResponse (). Таким чином, ви можете викликати getResponse (). SetEntity () з будь-якими даними, які ви хочете.


6

Виведіть його в будь-якому запитаному форматі. Це може бути:

<success>
    <id>5483</id>
</success>

Або:

{ "type": "success", "id": 5483 }

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


Добре, у мене є два можливі формати (html та xml). Я знаю, як обробляти тип запитуваного формату, але не знаю, як додати дані до відповіді. Представляє метод повертає Представлення, тому я просто повертаю те, що хотів, але acceptRepresentation - метод порожній, тому я не можу повернути будь-які дані ...
del-boy

1

Якщо ви відповідаєте 201 Створено тілом сутності, а не перенаправленням Розташування, то доцільно включити заголовок Content-Location, що вказує на ресурс, який представлений у відповіді.

Це дозволить уникнути потенційної плутанини - при якій клієнт може (виправдано) припустити, що сутність відповіді насправді представляє новий стан «творця», а не створений ресурс.

> POST /collection
> ..new item..

< 201 Created
< Location: /collection/1354
< Content-Location: /collection/1354
< <div class="item">This is the new item that was created</div>

3
Я вважаю, що Content-Location має іншу мету. Специфікація HTTP говорить, що вміст-розташування не визначено для POST та PUT. Заголовок Location використовується з 201-Create. Повернення адреси не робить автоматичного перенаправлення, для цього вам потрібен код відповіді 3XX.
Даррел Міллер 02

1
Заголовок розташування використовується (у відповіді 201), щоб вказати, де знаходиться створений ресурс; це не стосується органу суб'єкта господарювання відповіді, яке супроводжує. Моя думка полягала в тому, що - якщо ви хочете включити створений ресурс до самої відповіді 201 (а не направляти / перенаправляти клієнта на інший URI), тоді гарною ідеєю буде заголовок розташування вмісту. Можливо, це трохи «згинання правил», але це ефективніше, ніж вимагати чергового циклу запиту / відповіді, щоб отримати стан нового ресурсу для клієнта.
Майк 02

Майте сенс для мене. Я ніколи раніше не використовував заголовок Content-Location.
Даррел Міллер, 02

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

3
@irreputable: Я вважаю, що REST був призначений для проектування API, де A не означає User Agent, який шукає якийсь HTML для візуалізації.
Гермес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.