Створіть запит з POST, коди відповідей 200 або 201 та вміст


125

Припустимо, я пишу службу REST, мета якої - додати новий елемент даних до системи.

Я планую відправити до

http://myhost/serviceX/someResources

Припустимо, що працює, який код відповіді я повинен використовувати? І який вміст я можу повернути.

Я переглядаю визначення кодів відповідей HTTP і бачу ці можливості:

200: Поверніть об'єкт, що описує або містить результат дії;

201: що означає СТВОРЕНО. Значення * Запит було виконано, і це призвело до створення нового ресурсу. На новостворений ресурс можна посилатись на URI, повернуті в об'єкті відповіді, з найбільш конкретним URI для ресурсу, заданим полем заголовка Location. Відповідь ДОЛЖЕН включати сутність, що містить перелік характеристик ресурсів та місцеположення, з яких користувач або користувальницький агент можуть обрати найбільш відповідний. Формат сутності визначається типом носія, вказаним у полі заголовка Content-Type. *

Останнє звучить більше відповідно до специфікації Http, але мені зовсім не ясно, що

Відповідь ОБОВ'ЯЗКОВО включатиме сутність, що містить перелік характеристик ресурсів та місцеположення

засоби.

Рекомендації? Тлумачення?

Відповіді:


77

Ідея полягає в тому, що орган реагування надає вам сторінку, яка посилає вас на річ:

201 Створено

Код статусу 201 (Створений) вказує на те, що запит виконано і в результаті було створено один або кілька нових ресурсів. Первинний ресурс, створений запитом, ідентифікується або полем заголовка Location у відповіді, або, якщо не отримано поле Location, - ефективним URI запиту.

Це означає, що ви включите Locationв заголовок відповіді, який дає URL-адресу, де ви можете знайти новостворену річ :

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597

Орган реагування

Потім вони згадують, що слід включити до органу реагування :

Навантаження на відповідь 201 зазвичай описує та посилається на створений ресурс.

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

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: text/html

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

Якщо сторінку буде використовувати тільки робот, має сенс відповідь бути читаною на комп’ютері:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/xml

<createdResources>
   <questionID>1860645</questionID>
   <answerID>36373586</answerID>
   <primary>/a/36373586/12597</primary>
   <additional>
      <resource>http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586</resource>
      <resource>http://stackoverflow.com/a/1962757/12597</resource>
   </additional>
</createdResource>

Або, якщо ви віддаєте перевагу:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/json

{ 
   "questionID": 1860645, 
   "answerID": 36373586,
   "primary": "/a/36373586/12597",
   "additional": [
      "http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586",
      "http://stackoverflow.com/a/36373586/12597"
   ]
}

Відповідь повністю залежить від вас; це як завгодно, що б вам хотілося.

Кеш дружній

Нарешті, є оптимізація, що я можу попередньо кешувати створений ресурс (тому що у мене вже є вміст; я просто завантажив його). Сервер може повернути дату або ETag, які я можу зберігати із завантаженим мною вмістом:

Див. Розділ 7.2 для обговорення значення та призначення полів заголовка валідатора, таких як ETag та Last-Modified, у відповіді 201.

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/23704283/12597
Content-Type: text/html
ETag: JF2CA53BOMQGU5LTOQQGC3RAMV4GC3LQNRSS4
Last-Modified: Sat, 02 Apr 2016 12:22:39 GMT 

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

І ETags - суто довільні значення. Важливо, щоб вони відрізнялися, коли змінився ресурс (а кеші потрібно оновлювати) - це все, що має значення. ETag - це зазвичай хеш (наприклад, SHA2). Але це може бути база даних rowversionабо збільшення ревізійного номера. Все, що зміниться, коли річ зміниться.


Поки ти відповідь здається найбільш розумною. Я трохи занепокоєний онтологією відповіді, але окрім цього, це здається найбільш зрілою інтерпретацією специфікації. Мені цікаво, чи є якийсь легкий "чуйний" спосіб поводження з роботою людини / машини. але в основному мене заінтригує пропозиція "кешувати власні дані". Більшість веб-програм, які я знаю, не збираються створювати версію ресурсу 1: 1. Навіть якщо це щось тривіальне, як нормалізація написання великої літери. Хіба це не трохи химерно ставитися до поданої версії як до версії, для якої створений етаг?
Ентоні

1
@Anthony, кешування: це може бути програма для зберігання файлів 1: 1. Порівняйте, наприклад, WebDAV PUT & POST. Величезні файли для обробки.
kxr

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

Чому у ваших відповідях відсутня довжина вмісту?
Вінні Фалько

1
@VinnieFalco Це відповідь про код відповіді 201. Довжина вмісту була відмічена для цілей експозиції.
Ян Бойд

91

Я думаю, що atompub REST API - прекрасний приклад спокійного сервісу. Дивіться фрагмент нижче зі специфікації atompub:

POST /edit/ HTTP/1.1
Host: example.org
User-Agent: Thingio/1.0
Authorization: Basic ZGFmZnk6c2VjZXJldA==
Content-Type: application/atom+xml;type=entry
Content-Length: nnn
Slug: First Post

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
</entry>

Сервер сигналізує про успішне створення з кодом статусу 201. Відповідь включає заголовок Місцеположення, що вказує URI члена Входу Atom Entry, та представлення цього Входу в тілі відповіді.

HTTP/1.1 201 Created
Date: Fri, 7 Oct 2005 17:17:11 GMT
Content-Length: nnn
Content-Type: application/atom+xml;type=entry;charset="utf-8"
Location: http://example.org/edit/first-post.atom
ETag: "c180de84f991g8"  

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
  <link rel="edit"
      href="http://example.org/edit/first-post.atom"/>
</entry>

Запис, створений та повернутий колекцією, може не відповідати запису POSTed клієнтом. Сервер МОЖЕ змінити значення різних елементів у Записі, таких як atom: id, atom: оновлений, та atom: авторські значення, і МОЖЕТЕ вибрати видалити або додати інші елементи та атрибути, або змінити вміст та значення атрибутів.


9
Повернення створеного ресурсу може бути небагато, якщо ресурс знаходиться в гігабайти ...
Tor Valamo

10
Домовились! Це оптимізація необхідності - але ви не хочете робити це передчасно. Важливо проектувати в спокійних духах і робити винятки лише тоді, коли вони необхідні.
Чандра Патні

3
@ChandraPatni, Атом мертвий . Потрібні кращі приклади.
Пейсьєр

16
Атом може бути мертвим, але дух прикладу все ще помітний.
Ашимема

2
Моя оригінальна інтерпретація відповіді 201 більше нагадувала "ей, ти хотів створити ресурс, але виходячи з контексту, ти або не був зацікавлений у кінцевому результаті, або ти мав доступ до запису, але не читав доступ до цього ресурсу". випадку, все, що вам потрібно, перш ніж повернутися до основної колекції, - це URL-адреса створеного ресурсу. Як доказ він був створений ". По суті, все, що знаходиться поза цим, схоже на 200 відповідей. Якщо тільки RFC не мав на увазі щось інше.
Ентоні

50

Кілька слів:

  • 200, коли об’єкт створюється та повертається
  • 201, коли об’єкт створений, але повертається лише його посилання (наприклад, ідентифікатор або посилання)

Джерело для цього?
Судо соул


3
Прочитавши tools.ietf.org/html/rfc7231#section-6.3.1 , я погоджуюся з цим розумінням - я вважаю, що я питав більше, як ви до цього дійшли. Але зараз, на моє розуміння ... 200 = ресурс створений і повернутий | 201 = створений ресурс і повертається посилання | 204 = створено ресурс, і корисне навантаження не повернуто
sudo soul

34

Перевірте HTTP: Визначення методів: POST .

Дія, виконана методом POST, може не призвести до ресурсу, який можна ідентифікувати за допомогою URI. У цьому випадку або 200 (ОК), або 204 (Без вмісту) є відповідним статусом відповіді, залежно від того, включена у відповідь суб'єкт, який описує результат.

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


18

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19

Це просто розмежоване двокрапкою ключ-значення.

ETag: "xyzzy"

Це можуть бути будь-які типи текстових даних - я зазвичай включаю рядок JSON з ідентифікатором створеного елемента. Легкість тестування поодинці робить його в тому числі і вагомим.

ETag: "{ id: 1234, uri: 'http://domain.com/comments/1234', type: 'comment' }"

У цьому прикладі ідентифікатор, uri та тип створеного елемента - це "характеристики ресурсу та місцезнаходження".


3
Ви говорите, що ETag відповідає об'єкту, що містить перелік характеристик ресурсів та місцезнаходження . Я можу бачити, що Ваша пропозиція хороша, я дуже згоден з Вашою думкою щодо тестування. Однак я не бачу, як це вписується у "список характеристик ресурсів та місцеположення".
djna

"Перелік характеристик та розташування ресурсів" буде вмістом будь-якої структури даних. Більш сувора реалізація полягала б у тому, щоб структура JSON включала ресурс uri та, можливо, тип створеного ресурсу. Я скорегую відповідь як таку.
темпір

7
Вкажіть питання, щоб люди могли вчитися. В іншому випадку коментар просто махає руками.
темпір

@SimonGibbs Які проблеми?
ПАМ'ЯТ

2
Хоча це суворо правильно за специфікацією, він рекомендує дуже незвичний варіант реалізації. Крім того, він насправді не відповідає на питання вгорі сторінки (інакше це робиться шляхом змішування слів ETag та сутності). Відповідь з 43 голосами, мабуть, краща.
Саймон Гіббс

1

Вихідний сигнал фактично залежить від типу вмісту, який запитується. Однак як мінімум слід покласти ресурс, створений у Location. Так само, як шаблон пост-перенаправлення-отримання.

У моєму випадку я залишаю його порожнім, поки не вимагається інше. Оскільки така поведінка JAX-RS при використанні Response.create ().

Однак лише зауважте, що браузери та рамки, такі як Angular, не слідують 201-му автоматично. Я зазначив поведінку в http://www.trajano.net/2013/05/201-create-with-angular-resource/


-2

Ще одна відповідь, яку я хотів би зробити для цього, - це застосувати прагматичний підхід і забезпечити простий контракт на REST API . У моєму випадку я відремонтував свій REST API, щоб зробити речі більш випробуваними, не вдаючись до JavaScript або XHR, просто простих HTML-форм і посилань.

Тож, щоб бути більш конкретним у вашому питанні вище, я б просто скористався кодом повернення, 200а повернене повідомлення містить повідомлення JSON, яке ваша програма може зрозуміти. Залежно від ваших потреб, може знадобитися ідентифікатор новоствореного об’єкта, щоб веб-додаток міг отримати дані під час іншого дзвінка.

Одне зауваження, у моєму контракті на відновлення API відповіді POST не повинні містити кешованих даних, оскільки POST насправді не підлягають кеш-пам’яті, тому обмежте його ідентифікаторами, які можна запитувати та кешувати за допомогою GET-запиту.

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