Расщепление волос с помощью REST: нарушает ли стандартное API-интерфейс JSON REST HATEOAS? - PullRequest
40 голосов
/ 29 января 2012

Этим утром я читал REST и натолкнулся на принцип HATEOAS («гипермедиа как двигатель состояния приложения») .

Цитирование REST Wikipediapage :

Клиенты выполняют переходы состояния только посредством действий, которые сервер динамически идентифицирует в гипермедиа (например, по гиперссылкам в гипертексте).За исключением простых фиксированных точек входа в приложение, клиент не предполагает, что какие-либо конкретные действия будут доступны для каких-либо конкретных ресурсов, помимо тех, которые описаны в представлениях, ранее полученных от сервера.

И Блог Роя Филдинга :

... если механизм состояния приложения (и, следовательно, API) не управляется гипертекстом, то он не может быть RESTful и не может быть REST API.Период.

Я читаю это так: клиент может запрашивать изменения состояния только на основании действий, доступных из тела ответа от сервера (гипертекст).

в HTMLмир, это имеет смысл.Клиент должен иметь возможность запрашивать изменения состояния (новые действия / страницы) только на основании ссылок, предоставленных ему через гипертекст (HTML).

Когда ресурс представлен другими способами - такими как JSON,XML, YAML и т. Д. Это не так очевидно.

Давайте рассмотрим пример «REST» JSON API:

Я создаю новый ресурс (например, новый комментарий), отправив запрос POSTна

/comments.json? # with params...

Сервер отвечает:

# Headers
HTTP/1.1 201 Created 
Location: http://example.com/comments/3
Content-Type: application/json; charset=utf-8
... Etc.

# Body
{"id":3,"name":"Bodacious","body":"An awesome comment","post_id":"1"}

Я знаю, что теперь я могу получить доступ к этому комментарию по URI, возвращенному в заголовке: http://example.com/comments/3.json

Когда я посещаю http://example.com/comments/3.json, я вижу:

{"id":3,"name":"Bodacious","body":"An awesome comment","post_id":"1"}

Предположим, что документация API говорит мне, что я могу удалить этот комментарий, отправив запрос DELETE на тот же URI.Это довольно часто встречается среди API "REST".

Однако:

Ответ от сервера на GET http://example.com/comments/3.json ничего не говорит мне о возможности удалить комментарий, отправив DELETEзапрос.Все, что мне показывает, это ресурс.

То, что я также могу УДАЛИТЬ комментарий с тем же URL-адресом, - это то, что клиент знает через внеполосную информацию (документацию) и не обнаруживается и не управляется ответом от сервера.

Здесь клиент имеет значение , предполагая, что действие DELETE (и возможные другие) доступны для этого ресурса, и эта информация ранее не была получена с сервера.

Я неправильно понял HATEOASили я прав, говоря, что API, соответствующий приведенному выше описанию, не будет, в строгом смысле, REST API?

Я знаю, что 100% -ное соблюдение REST не всегда возможно или наиболее прагматичноидти.Я разместил этот вопрос исключительно для того, чтобы удовлетворить свое собственное любопытство по поводу теории, лежащей в основе REST, а не для советов по наилучшей практике в реальном мире.

Ответы [ 6 ]

20 голосов
/ 11 февраля 2012

Джон Мур дал превосходную беседу в ноябре 2010 года об основных моментах написания действительно RESTful (т. Е. Поддержки HATEOAS) API и клиента. В первой части он предполагает, что JSON не является подходящим типом мультимедиа для REST, поскольку в нем отсутствует общепринятый способ представления ссылок и поддерживаемые методы HTTP. Он утверждает, что хороший старый XHTML на самом деле идеально подходит для этого, поскольку инструменты для его анализа (например, XPath) легко доступны, он поддерживает формы (например, шаблоны GET link и шаблоны PUT, POST и DELETE) и имеет хорошо понятый способ выявление гиперссылок, а также некоторые другие преимущества, в основном благодаря возможности использовать API с любым стандартным веб-браузером (облегчает работу для разработчиков, QA и персонала службы поддержки).

Аргумент, который я всегда приводил перед просмотром его выступления, заключается в том, что JSON намного меньше потребляет пропускную способность, чем любой язык * ML, например. XML, HTML, XHTML. Но при использовании краткого XHTML, где это возможно, такого как относительные ссылки вместо абсолютных (намекало на это, но не очень очевидно в примере, который он использует в своей речи), и при использовании сжатия gzip этот аргумент теряет вес.

Я понимаю, что такие усилия, как JSON-схема и другие RFC, предпринимаются для того, чтобы попытаться стандартизировать вещи в JSON, но в то же время доклад Мура убедил меня попробовать XHTML.

18 голосов
/ 30 января 2012

JSON как тип гипермедиа не определяет идентификатор для потока приложения. HTML имеет ссылку и тег формы, которые направляют пользователя через процесс.

Если ваше приложение касается только PUT, POST, DELETE, GET для ресурса, ваша документация может легко объяснить это.

Однако, если бы это было более сложным, например, добавление опровержения к комментарию, и это опровержение было другим ресурсом, тогда для комментария вам понадобился бы гипермедиа, который помог бы потребителю создать опровержение.

Вы можете использовать HTML / XHTML, создать свой собственный «bodacious + json» или использовать что-то еще. Вот все разные типы носителей http://www.iana.org/assignments/media-types/index.html

Я использую HAL, и у него довольно активная группа. Вот ссылки на него.

http://www.iana.org/assignments/media-types/application/vnd.hal+json

http://stateless.co/hal_specification.html

Книга "Построение гипермедиа API с HTML5 и Node" углубляется в гипермедиа и медиа типы. В нем показано, как создать тип мультимедиа для определенной или общей цели в XML или JSON.

15 голосов
/ 30 января 2013

RESTful решение будет использовать Разрешить заголовок для информирования клиента о доступных методах / действиях:

> GET /posts/1/comments/1 HTTP/1.1
> Content-Type: application/json
>
< HTTP/1.1 200 OK
< Allow: HEAD, GET, DELETE
< Content-Type: application/json
<
< {
<  "name": "Bodacious",
<  "body": "An awesome comment",
<  "id":   "1",
<  "uri": "/posts/1/comments/1"
< }

Диссертация Филдинга устанавливает два типа метаданных: метаданные представления ; и метаданные ресурса .

Заголовок Allow в HTTP / 1.1 функционирует как метаданные ресурса , потому что он описывает некоторое свойство ресурса; то есть методы, которые это позволяет.

Полностью используя функции, предоставляемые HTTP, вы устраняете необходимость в за пределами информации и повышаете RESTful.

HATEOAS в простом контексте HTTP описывает, как клиент может переходить из одного представления в другое, следуя URI, используя GET , в то время как заголовок Allow информирует клиента о дополнительных методах, поддерживаемых сгенерированным ресурсом представление.

Это аккуратный дизайн; клиент запросил представление и дополнительно получил целый набор дополнительных метаданных о ресурсе, что позволяет эффективно запрашивать дальнейшие представления.

Я думаю, что цитата, которую вы получили со страницы REST в Википедии, несколько вводит в заблуждение в выборе слов и здесь не помогла (примечание: она была улучшена с тех пор, как был задан этот вопрос).

Все клиенты HTTP должны предполагать, что GET-метод, вероятно, будет доступен для большинства ресурсов. Они делают это, потому что поддержка GET и HEAD является минимальными требованиями для сервера HTTP / 1.1. Без этого предположения сеть не будет функционировать. Если клиент может предположить, что GET доступен, то почему бы не сделать другие предположения относительно распространенных методов, таких как DELETE или POST ?

REST и HTTP нацелены на использование возможностей делать предположения об основном наборе методов, чтобы уменьшить общий объем запросов в сети; в случае успешного выполнения запроса дальнейшая связь не требуется; но если запрос терпит неудачу со статусом «405 Method Not Allowed», то клиент немедленно получает запросы, которые могут быть успешно выполнены через Allow-header:

> ANNIHILATE /posts/1/comments/1 HTTP/1.1
> Content-Type: application/json
>
< HTTP/1.1 405 Method Not Allowed
< Allow: HEAD, GET, DELETE
< Content-Type: application/json
<

Если базового набора методов HTTP / 1.1 недостаточно, вы можете сами определить свой собственный. Однако было бы RESTful решать проблемы, используя доступные функции HTTP, прежде чем определять новые методы или помещать метаданные в тело сообщения.

8 голосов
/ 18 октября 2012

Полностью обнаруживаемый JSON API, который не требует каких-либо внеполосных знаний, как вы выразились так кратко:

«То, что я также могу УДАЛИТЬ комментарий с тем же URL-адресом, - это то, что клиент знает по внеполосной информации (документации) и не обнаруживается и не управляется ответом от сервера».

... вполне возможно. Это просто требует простого стандарта и клиента, который понимает стандарт. Проверьте hm-json и проект браузера hm-json:

https://bitbucket.org/ratfactor/hm-json-browser/

Как вы можете видеть в демонстрации, совершенно не требуется внеполосной документации - только один URI точки входа, из которого все другие ресурсы и их методы HTTP могут быть обнаружены при просмотре.

Кстати, HAL, как упомянуто в ответе Сью, очень, очень близко соответствует вашим гипотетическим требованиям для HATEOAS. Это отличный стандарт, и в нем есть много интересных идей, таких как встроенные ресурсы, но он не может информировать клиента обо всех доступных HTTP-методах, таких как DELETE для данного ресурса.

4 голосов
/ 22 июля 2013

Другая надежная (и новая по состоянию на май 2013 г.) попытка разрешения HATEOAS для JSON может быть найдена здесь:

JSON API: http://jsonapi.org/

3 голосов
/ 11 мая 2014

Предпосылка вашего вопроса содержит часто неправильно истолкованный аспект REST - то, что сущность тела ответа API будет не только сообщать о состоянии представления запрашиваемого ресурса, но и сообщать обо всем состоянии приложения.ресурс принадлежит .Эти две вещи - состояние ресурса и состояние приложения - не одно и то же.

Тело объекта ответа по определению предоставляет вам состояние ресурса в определенный момент времени.Но один ресурс - это только один из многих, которые составляют приложение.Состояние приложения - это объединенные состояния всех связанных с областью ресурсов - в любой момент времени - с точки зрения потребителя приложения - человека или машины.Чтобы обеспечить это «состояние приложения», API-интерфейс REST уровня 3 делает возможным использование HATEOAS.

Поскольку гипертекст - это то, что большинство людей имеет в виду, когда ссылается на «Гипермедиа» в HATEOAS, особая сила гипертекста заключается в его способности связыватьв другие СМИ.Кроме того, поскольку в большинстве случаев использование гипертекста через HTTP / HTML приводит к тому, что многие думают, что гиперссылки возможны только через тег привязки или тег ссылки внутри тела объекта ответа, но это не так.

Еслитранспортным протоколом является HTTP, тогда состояние приложения может и должно передаваться через заголовки.В частности, один или несколько заголовков 'Link' с атрибутом 'rel' для обеспечения семантики.Link HEADER вместе с заголовком ALLOW являются HTTP-механизмами для передачи информации о том, каковы следующие возможные переходы состояний и как получить к ним доступ.

Если вы решите не использовать эти встроенные механизмы, тогда вы можете попытаться сообщить о состоянии приложения, «прокручивая» его на своем канале связи состояния ресурса, то есть в теле ответа, что приводит к попыткеРазработать некоторую форму дополнительной спецификации в дизайне самого ресурса.

Когда это сделано - «копирование» - многие сталкиваются с проблемами типа контента, потому что тело ответа должно быть задано MIME / типом контента, таким как XML или JSON, что означает выяснение того, как реализоватьмеханизмы HATEOAS через некоторый пользовательский формат, специфичный для типа контента, такой как пользовательские теги XML или пары ключ: значение вложенного объекта.Вы можете сделать это, многие делают, например, см. Предложение json-api выше, но опять же HTTP уже предоставляет механизмы для этого.

Я думаю, что это идет к нам, поскольку люди всегда думают, что мы должны видеть или быть в состоянии щелкнутьна этих ссылках, как в обычном веб-сценарии использования, но мы говорим об API, которые, как я могу только предположить, создаются не для потребления человеком, а для потребления машиной - верно?Тот факт, что заголовки - которые, кстати, присутствуют как часть ответа - не видны в большинстве человеческих интерфейсов с HTTP, т. Е. В браузерах, - это не проблема REST, а скорее ограничение реализации агентов HTTP на рынке.

Надеюсь, это поможет.Кстати, если вам нужен хороший человеческий браузер для API, Google Paw API Browser

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