Создайте запрос с помощью POST, коды ответов 200 или 201 и содержание - PullRequest
95 голосов
/ 07 декабря 2009

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

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

http://myhost/serviceX/someResources

Предположим, что это работает, какой код ответа я должен использовать? И какой контент я могу вернуть.

Я смотрю на определения кодов ответов HTTP и вижу следующие возможности:

200: вернуть объект, описывающий или содержащий результат действия;

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

Последнее звучит больше в соответствии со спецификацией Http, но мне не совсем понятно, что

Ответ ДОЛЖЕН включать в себя объект содержащий список ресурсов характеристики и местонахождение (я)

означает.

Рекомендации? Интерпретации?

Ответы [ 7 ]

82 голосов
/ 27 декабря 2009

Я думаю, API REST atompub является отличным примером спокойного сервиса. Смотрите фрагмент ниже из спецификации 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. Ответ включает в себя заголовок Location, указывающий URI записи элемента в записи Atom, и представление этой записи в теле ответа.

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>

Запись, созданная и возвращенная коллекцией, может не совпадать с записью, выставленной клиентом. Сервер МОЖЕТ изменить значения различных элементов в Entry, таких как значения atom: id, atom: updated и atom: author, и МОЖЕТ выбрать удаление или добавление других элементов и атрибутов или изменение содержимого элемента и значений атрибутов.

55 голосов
/ 02 апреля 2016

Идея состоит в том, что тело ответа дает вам страницу, которая связывает вас с вещью:

201 Создано

Код состояния 201 (Создан) указывает, что запрос был выполнен и привел к созданию одного или нескольких новых ресурсов. Основной ресурс, созданный запросом, идентифицируется либо полем заголовка Location в ответе, либо, если поле Location не получено, эффективным URI запроса.

Это означает, что вы бы включили Location в ответ header , который дает URL-адрес, где вы можете найти недавно созданную вещь :

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

Тело ответа

Затем они упоминают, что вы должны включить в ответ body :

Полезная нагрузка ответа 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="/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>/1376194/sozdaite-zapros-s-pomoschy-post-kody-otvetov-200-ili-201-i-soderzhanie</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": [
      "/1376194/sozdaite-zapros-s-pomoschy-post-kody-otvetov-200-ili-201-i-soderzhanie",
      "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="/a/36373586/12597">here</A> to view it.

И ETag с являются чисто произвольными значениями. Иметь их по-разному, когда ресурс меняется (а кэши нужно обновлять) - это все, что имеет значение. ETag обычно представляет собой хеш (например, SHA2). Но это может быть база данных rowversion или инкрементный номер ревизии. Все, что изменится , когда вещь изменится.

27 голосов
/ 17 мая 2014

Check HTTP: определения методов: POST .

Действие, выполняемое методом POST, может не привести к ресурсу, который может быть идентифицирован по URI. В этом случае либо 200 (ОК), либо 204 (Нет содержимого) - это соответствующий статус ответа, в зависимости от того, содержит ли ответ объект, описывающий результат.

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

26 голосов
/ 06 июня 2017

В двух словах:

  • 200 при создании объекта и возвращено
  • 201 когда объект создается, но возвращается только его ссылка (например, идентификатор или ссылка)
12 голосов
/ 26 декабря 2009

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 и тип созданного элемента являются «характеристиками ресурса и местоположением».

1 голос
/ 03 мая 2013

Вывод фактически зависит от запрашиваемого типа контента. Однако, как минимум, вы должны поместить ресурс, созданный в Location. Как и шаблон Post-Redirect-Get.

В моем случае я оставляю это поле пустым, пока не будет запрошено иначе. Так как это поведение JAX-RS при использовании Response.created ().

Тем не менее, просто отметьте, что браузеры и фреймворки, такие как Angular, не следуют за 201 автоматически. Я отметил поведение в http://www.trajano.net/2013/05/201-created-with-angular-resource/

0 голосов
/ 23 июля 2014

Другой ответ, который у меня был бы для этого, состоял бы в том, чтобы принять прагматичный подход и сделать ваш REST API контракт простым. В моем случае я реорганизовал свой REST API, чтобы сделать его более тестируемым, не прибегая к JavaScript или XHR, просто к простым HTML-формам и ссылкам.

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

Одно примечание: в моем рефакторированном контракте API ответы POST не должны содержать никаких данных, которые могут быть кэшированы, поскольку POST на самом деле не кэшируются, поэтому ограничьте их идентификаторами, которые можно запрашивать и кэшировать с помощью запроса GET.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...