А ваша служба является RESTful? Все что необходимо-обязательно знать про веб службы и REST

в 7:45, , рубрики: api, json-rpc, rest, RESTful, richardson maturity model, RMM, soap, xml-rpc, Программирование, Разработка веб-сайтов

Введение

Вот не люблю я изобретать велосипед и статью я бы эту не написал, но пришлось. Про REST сказано уже довольно много. Многие поставщики веб служб готовы клясться, что их службы являются RESTful. Во время собеседования вы точно услышите хотя бы несколько вопросов про REST, независимо от того это собеседования для бэкенд, мобайл или фронтенд разработчика. Я вот помню как-то во время одного собеседования меня задали такой вопрос: «Вот вы написали в своем резюме, что знайте REST․ Ответьте пожалуйста, какой HTTP код вы получите, если при запросе к RESTful сервису ресурс не найден?». Ответ 404 был принят единогласно. Если честно, я так и не понял, как этот вопрос помог понять знаю ли я REST или нет, но одно могу уверенно сказать: REST понимают далеко не все. Вот некоторые вопросы, которые мучали меня долгое время:

  1. Зачем REST стал таким трендовым? Это архитектура была же предложена еще в 2000 году?
  2. Что я получу если моя служба будет RESTful?
  3. Как определить является ли служба RESTful или нет?
  4. Как правильно должны создаваться URL REST служб?
  5. Какие http методы и коды должны быть использованы в RESTful службе?

Если вы не можете дать исчерпывающего ответа хотя бы на один из этих вопросов, то продолжайте чтение. Если вы можете однозначно ответить на все эти вопросы, можете привести формат правильного URL, считайте, что GET, POST, PUT, DELETE обязательно должны соответствовать CRUD операциям с ресурсами, то вам обязательно надо продолжать чтение.

Чтобы найти ответы на приведенные вопросы и представить общую картину пришлось прочитать кучу спецификаций, диссертацию Роя Филдинга и книгу Леонарда Ричардсона, поскольку оказалось что есть большая путаница в интернете и в частности в Stack Overflow. Найденная информацию показалось мне довольно полезной вот и решил им с вами поделиться.

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

Ну что же, начнем путешествие в мир веб-сервисов.

SOA & Web Services

SOA, расширяемая как сервис ориентированная архитектура (Service Oriented Architecture), является парадигмой для организации и использования распределенных систем, которые могут находиться под контролем различных областей собственности [1]. В SOA, под service подразумевается функциональная возможность, которая удовлетворяет следующим критериям [2]։

  1. Представляет собой функциональность с конкретным результатом.
  2. Является самодостаточным (self-contained).
  3. Является черным ящиком для клиентов.
  4. Может состоять из других услуг.

Service Description – это информация о сервисе, необходимая для взаимодействия со службой (пр. WSDL).
Service Provider – это люди или организации, которые предоставляют сервисы.
Service Consumer – это клиенты, потребители служб.

Web Service, согласно определению [3], является системой, предназначенная для взаимодействия машин/программ по сети. Веб-сервис должен иметь интерфейс, описанной в машинно-обрабатываемом формате (service description). Другие системы должны взаимодействовать с веб-сервисом посредством сообщений.

Взаимосвязь между веб-сервисом и SOA является то, что SOA может быть реализован посредством веб-сервисов.

Если вас заинтересует какие еще методы существуют или существовали для реализации SOA, можете посмотреть COM и CORBA.

Протоколы веб служб

До того, как решить какая служба является RESTful, а какая нет, рассмотрим некоторые реализации, или как по другому их называют, протоколы веб служб. Список общеизвестных протоколов веб служб можно найти в [4].

1. XML-RPC

Протокол XML-RPC (XML Remote Procedure Call) [5] был в первые опубликован в 1999 году. Все сообщение XML-RPC являются HTTP-POST запросами. Для шифрования сообщений используется XML. Параметры процедуры могут быть скалярные значения, числа, строки, даты, массивы и структуры. Ответ веб службы может хранить либо значение, возвращаемой процедурой, либо код и сообщение ошибки.

Пример запроса и ответа (пример приведен из самой спецификации [5]):

Host: betty.userland.com
Content-Type: text/xml
Content-length: 181
<?xml version="1.0"?>
<methodCall>
   <methodName>examples.getStateName</methodName>
   <params>
      <param>
         <value><i4>41</i4></value>
         </param>
      </params>
   </methodCall>

HTTP/1.1 200 OK
Connection: close
Content-Length: 158
Content-Type: text/xml
Date: Fri, 17 Jul 1998 19:55:08 GMT
Server: UserLand Frontier/5.1.2-WinNT
<?xml version="1.0"?>
<methodResponse>
   <params>
      <param>
         <value><string>South Dakota</string></value>
         </param>
      </params>
   </methodResponse>

В качестве недостатка протокола XML-RPC, приводится большой размер сообщений (4 раза больше, по сравнению с обычным XML) и не существования языка описания веб-сервиса (что-то похожее на WSDL), который мог был бы использоваться для генерации прокси классов на стороне клиента.

2. JSON-RPC

Протокол JSON-RPC [6], опубликованный в 2009 году, по своим принципам работы очень похож на XML-RPC. Главными отличиями являются способ шифрования данных, независимость от транспортного уровня, способность передачи извещений (notification request) и возможность идентификации ответов при отправке нескольких запросов одновременно.

Для шифрования данных в JSON-RPC используется JSON. Кроме имени процедуры и параметров, в запросе указывается также значение id, который используется для идентификации ответа на стороне клиента. Другими словами если вы отправили запрос с id=12345, то ответ этого запроса обязательно должен возвращать сообщение с id=12345.

Извещение – это специальные запросы, на которые сервер может не отвечать. Для отметки запроса, как извещение, значения параметра id указывается = null.

Независимость от транспортного уровня можно обусловить только тем, что в спецификации JSON-RPC [6] HTTP не указывается обязательным протоколом. При использовании JSON-RPC над HTTP, необходимо использовать POST запросы.

Пример JSON-RPC запроса и ответа:

--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}

--> {"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}
<-- {"jsonrpc": "2.0", "result": 19, "id": 3}

Недостатком JSON-RPC, как и в случае XML-RPC является отсутствие языка описания веб-сервиса (аналог WSDL).

3. SOAP

Протокол SOAP (Simple Object Access Protocol) [7] является наследником XML-RPC. Основными характеристиками SOAP являются:

  1. Все передаваемые сообщения шифруются с помощью XML (SOAP messages).
  2. Все SOAP службы имеют описание на языке WSDL, которое тоже является XML-ом. Это позволяет клиентом автоматически сгенерировать прокси классы.
  3. SOAP поддерживает почти все известные протоколы TCP/IP (TCP, UDP, HTTP, SMTP, FTP и т.д.). Именно по этой причине SOAP является довольно сложным протоколом по сравнению с предыдущими.
  4. При использовании HTTP, поддерживается как метод GET так и POST. GET допускается использовать только для получения данных, т.е. на стороне сервера нe должно ничего меняться. POST можно использовать для всех случаев. На практике обычно используется только POST.

Главным недостатком SOAP является его сложность по причине гибкости. Другой немало важным недостатком является поддержка шифрование только в XML.

Пример SOAP запроса и ответа :

HTTP GET:

GET /travelcompany.example.org/reservations?code=FT35ZBQ  HTTP/1.1
Host: travelcompany.example.org
Accept: text/html;q=0.5, application/soap+xml

HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
       env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-30T16:25:00.000-05:00</m:dateAndTime>
  </m:reservation>
 </env:Header>
 <env:Body>
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
            xmlns:x="http://travelcompany.example.org/vocab#"
     env:encodingStyle="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
   <x:ReservationRequest 
 rdf:about="http://travelcompany.example.org/reservations?code=FT35ZBQ">
      <x:passenger>Åke Jógvan Øyvind</x:passenger>
      <x:outbound>
       <x:TravelRequest>
        <x:to>LAX</x:to>
        <x:from>LGA</x:from>
        <x:date>2001-12-14</x:date>
       </x:TravelRequest>
      </x:outbound>
      <x:return>
       <x:TravelRequest>
        <x:to>JFK</x:to>
        <x:from>LAX</x:from>
        <x:date>2001-12-20</x:date>
       </x:TravelRequest>
      </x:return>
    </x:ReservationRequest>
  </rdf:RDF>
 </env:Body>
</env:Envelope>

HTTP POST:

POST /Reservations HTTP/1.1
Host: travelcompany.example.org
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
   <t:transaction
           xmlns:t="http://thirdparty.example.org/transaction"
           env:encodingStyle="http://example.com/encoding"
           env:mustUnderstand="true" >5</t:transaction>
 </env:Header>  
 <env:Body>
  <m:chargeReservation
     env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
          xmlns:m="http://travelcompany.example.org/">
   <m:reservation xmlns:m="http://travelcompany.example.org/reservation">
    <m:code>FT35ZBQ</m:code>
   </m:reservation>
    <o:creditCard xmlns:o="http://mycompany.example.com/financial">
     <n:name xmlns:n="http://mycompany.example.com/employees">
           Åke Jógvan Øyvind
     </n:name>
     <o:number>123456789099999</o:number>
     <o:expiration>2005-02</o:expiration>
    </o:creditCard>
   </m:chargeReservation
  </env:Body>
</env:Envelope>

HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
       ...
       ...
 </env:Header>  
 <env:Body>
       ...
       ...
 </env:Body>
</env:Envelope>

REST

REST является на сегодняшний день наверное самым популярным веб-сервис протоколом.

На самом деле REST вовсе не является протоколом и оно вообще не новое. REST является архитектурой который был предложен в 2000-ие годы Роем Филдингом в его диссертации «Architectural Styles and the Design of Network-based Software Architectures» [8]. До этого REST архитектура была использована в многих проектах в рамках IETF и W3C. В самой диссертации вы не сумейте найти терминов «веб служба» или SOA. REST архитектура была предложена для правильного конструирования распределенных гипермедиа систем, по другим словом того, что на сегодня называется World Wide Web. Чтобы диссертацию Филдинга вы приняли в серьез, скажу, что Рой является архитектором HTTP 1.1, соавтором интернет стандартов для HTTP и URI [10]. В общем мужик он серьезный и известный.

Чтобы распределенная система считалась сконструированной по REST архитектуре, необходимо, чтобы она удовлетворяла следующим критериям:

  1. Client-Server. Система должна быть разделена на клиентов и на серверов.
  2. Stateless. Сервер не должен хранить какой-либо информации о клиентах. В запросе должна храниться вся необходимая информация для обработки запроса и если необходимо, идентификации клиента.
  3. Cache․ Каждый ответ должен быть отмечен является ли он кэшируемым или нет.
  4. Uniform Interface. Универсальный интерфейс между компонентами системы.

    Для получения универсального интерфейса вводятся следующие ограничения:

    • Identification of resources.

      В REST ресурсом является все то, чему можно дать имя. Например, пользователь, HTML документ, изображение, регистрированный пользователь, красная майка, голодная собака, текущая погода и т.д. Каждый ресурс в REST должен быть идентифицирован посредством стабильного идентификатора, который не меняется при изменении состояния ресурса. В нашем случае идентификатором в REST является URI.

    • Manipulation of resources through representations.

      Представление в REST используется для выполнения действий над ресурсами. Представление ресурса представляет собой текущее или желаемое состояние ресурса. Например, если ресурсом является пользователь, то представлением может является XML или HTML описание этого пользователя.

    • Self-descriptive messages.

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

    • HATEOAS (hypermedia as the engine of application state).

      Данный пункт означает, что гипертекст должен быть использован, для навигации по API [9]. Отмечу, что в случае SOA, для этого используется service description.

      Рассмотрим данный пункт более подробно.

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

      GET /account/12345 HTTP/1.1
      
      HTTP/1.1 200 OK
      <?xml version="1.0"?>
      <account>
          <account_number>12345</account_number>
          <balance currency="usd">100.00</balance>
          <link rel="deposit" href="/account/12345/deposit" />
          <link rel="withdraw" href="/account/12345/withdraw" />
          <link rel="transfer" href="/account/12345/transfer" />
          <link rel="close" href="/account/12345/close" />
      </account>
      

      Рассмотрим этот же пример при негативном балансе:

      GET /account/12345 HTTP/1.1
      
      HTTP/1.1 200 OK
      <?xml version="1.0"?>
      <account>
          <account_number>12345</account_number>
          <balance currency="usd">-25.00</balance>
          <link rel="deposit" href="/account/12345/deposit" />
      </account>
      

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

  5. Layered System. В REST допускается разделить систему на иерархию слоев но с условием, что каждый компонент может видеть компоненты только непосредственно следующего слоя. Например, если вы вызывайте службу PayPal а он в свою очередь вызывает службу Visa, вы о вызове службы Visa ничего не должны знать.
  6. Code-On-Demand. В REST позволяется загрузка и выполнение кода или программы на стороне клиента.

И так, если распределенная система удовлетворяет всем шести приведенным пунктам, то можно сказать что она устроена по архитектуре REST, а такая веб служба в этом случае называется RESTful службой.

Как вы уже заметили в этих пунктах ничего не сказано про GET, PUT, POST и DELETE запросы, шифрование JSON, HTTP и т.д.

REST – это просто архитектура, он никак не привязан к каким либо протоколом.

Наверняка вы уже заметили, что в REST архитектуре нет ничего удивительного и нового. Нового было в REST в 2000 году, когда веб только-только начал развиваться. Чтобы еще лучше представить REST и его значимость, представьте, что веб – это распределенная система гипермедиа, где каждый сайт представляет собой гипертекст.

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

REST & Richardson Maturity Model

И так, как же связан REST с веб службами? Какие службы можно считать RESTful, а какие нет? Что вы получите, если ваша служба будет удовлетворять всем пунктам Филдинга? Отвечу на эти вопросы по очереди:

  1. REST архитектура оправдала себя в течении последних 16-и лет на практике веба. Поскольку веб-сервисы являются частью веба, многими компаниями/разработчиками/исследователями было решено и в случае веб-сервисов применить архитектуру REST, что позволит улучшить масштабируемость компонентов, обеспечить безопасность, независимое развертывание и т.д.
  2. Если веб служба удовлетворяет всем критериям Филдинга, то его можно считать RESTful, независимо от того, используется ли HTTP метод DELETE для удаления записей или нет. Добавлю, что в веб часто используемыми методами являются GET и POST и если веб служба должна быть максимально похожим на веб, то использовать PUT и DELETE тоже как-то не правильно.
  3. Хотя Филдинг писал про веб и распределенную систем гипертекстов, все равно скопирую часть из его диссертации. По английский звучит более убедительно.

    REST provides a set of architectural constraints that, when applied as a whole, emphasizes scalability of component interactions, generality of interfaces, independent deployment of components, and intermediary components to reduce interaction latency, enforce security, and
    encapsulate legacy systems.

Звучит конечно все очень круто, но надо ли чтобы ваш веб-сервис был сконструирован по REST или это просто тренд? Давайте рассмотрим модель RMM (Richardson Maturity Model) Леонарда Ричардсона.

После анализа нескольких сотен веб-сервисов [11] был предложен модель RMM для оценки качества, или как Ричардсон назвал это, зрелости веб-сервиса. Модель RMM состоит из 4 уровня. Если ваш сервис соответствует последнему уровню, то можно считать его RESTful. Ниже я приведу примеры и рисунки из [12], которые по словам автора были проверены Аароном Шварцем, Леонардом Ричардсоном и другими известными лицами. Все примеры основаны на следующей истории: Я хочу записаться на прием у врача. От веб службы мне нужно получить свободные часы приема на конкретную дату и после записаться на прием. И так, рассмотрим все эти четыре уровня на данном примере.

Уровень 0: Один URI, один HTTP метод.

Здесь HTTP используется только для взаимодействия компонентов распределенной системы. Из методов используется только один, например POST. Как вы уже догадались, такими веб-сервисами являются протоколы XML-RPC и SOAP.

image

Пример: Получение свободных часов доктора mjones на дату 2010-01-04.

POST /appointmentService HTTP/1.1
[various other headers]
<openSlotRequest date = "2010-01-04" doctor = "mjones"/>

HTTP/1.1 200 OK
[various headers]

<openSlotList>
  <slot start = "1400" end = "1450">
    <doctor id = "mjones"/>
  </slot>
  <slot start = "1600" end = "1650">
    <doctor id = "mjones"/>
  </slot>
</openSlotList>

Пример: Регистрация на прием к доктору mjones с 14:00 до 14:50. (тут в запросе наверно нужно было бы еще дату указать, но оригинальный пример не буду менять).

POST /appointmentService HTTP/1.1
[various other headers]

<appointmentRequest>
  <slot doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointmentRequest>

HTTP/1.1 200 OK
[various headers]

<appointment>
  <slot doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointment>

XML используется тут только для примера, в его месте мог был быть JSON, HTML и т.д. Веб-сервис имеет только один URL (относительный URL): /appointmentService. Запрашиваемая функция указывается в теле запроса.

Если ваш сервис соответствует уровню 0, то он еще ребенок.

Теперь рассмотрим этот же пример при работе с веб-сервисом с уровнем 1.

Уровень 1: Несколько URI, один HTTP метод.

Службы этого уровня используют понятие «разделяй и властвуй». В службе вводится понятие ресурсов и для действия с конкретным ресурсом используется URL этого ресурса.

image

Пример: Получение свободных часов доктора mjones на дату 2010-01-04.

POST /doctors/mjones HTTP/1.1
[various other headers]

<openSlotRequest date = "2010-01-04"/>

HTTP/1.1 200 OK
[various headers]

<openSlotList>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>
</openSlotList>

Пример: Регистрация на прием к доктору mjones с 14:00 до 14:50.

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
  <patient id = "jsmith"/>
</appointmentRequest>

HTTP/1.1 200 OK
[various headers]

<appointment>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointment>

И так, если вы хотите выполнить какое-то действие с доктором, то надо использовать относительный URL /doctors, а если ваше действие связано с посещением, то URL /slots. Если сравнить службу первого уровня со службой нулевого уровня, то в последнем случае есть только один ресурс, и этот ресурс сама веб служба.

Если ваш сервис соответствует уровню 1, то он является подростком.

Уровень 2: Несколько URI, каждый поддерживает разные HTTP методы (Правильное использование HTTP).

И так, на уровне 1 все методы веб службы были отделены с помощью ресурсов, но с ресурсом можно выполнить кучу действий. Чтобы эти действия тоже были как-то логически разделены, используется возможность HTTP отправлять и принимать операции с разними методами: GET, HEAD, POST, PUT, DELETE, TRACE, CONECT. Например, если метод является чтением, можно использовать GET, если для создания POST или PUT․ В принципе, можно и наоборот, но поскольку в HTTP эти методы имеют какие-то понятия и характеристики, лучше, чтобы эти понятия были те же, что и в веб службе, в противном случае вы можете получить кэшируемый метод создания ресурса. Другими словами, какой метод вы будете использовать для каких операций, уже вопрос правильного использования протокола HTTP․

image

Наверное, пришло время для примеров:

Пример: Получение свободных часов доктора mjones на дату 2010-01-04.

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1
Host: royalhope.nhs.uk

HTTP/1.1 200 OK
[various headers]

<openSlotList>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>
</openSlotList>

Пример: Регистрация на прием к доктору mjones с 14:00 до 14:50.

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
  <patient id = "jsmith"/>
</appointmentRequest>

HTTP/1.1 201 Created
Location: slots/1234/appointment
[various headers]

<appointment>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointment>

С вводом разных HTTP методов вводится также необходимость возвращения правильных HTTP статус кодов. Например, на запрос создания встречи, если она создана, то должен быть возвращен код 201. Если в течении ваших действий кто-то уже регистрировался на выбранный день и час, должен быть возвращен код 409 conflict и т.д. Опять же, тут дело в правильном использовании протокола HTTP․

Если ваш сервис соответствует уровню 2, то он является уже взрослой мужчиной.

Уровень 3: HATEOAS․ Ресурсы сами описывают свои возможности и взаимосвязи.

HATEOAS (Hypertext as the Engine of Application State), требование которое на мой взгляд обязателен для гипермедиа, но насколько это актуален для веб служб — не знаю. Все же, HATEOAS – это характеристика веб-сервиса возвращать действия в виде URL, которые могут быть выполнены с интересующим вам ресурсом.

image

Поскольку HATEOAS был уже рассмотрен выше, тут я приведу только примеры.

Пример: Получение свободных часов доктора mjones на дату 2010-01-04.

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1
Host: royalhope.nhs.uk

HTTP/1.1 200 OK
[various headers]

<openSlotList>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450">
     <link rel = "/linkrels/slot/book" 
           uri = "/slots/1234"/>
  </slot>
  <slot id = "5678" doctor = "mjones" start = "1600" end = "1650">
     <link rel = "/linkrels/slot/book" 
           uri = "/slots/5678"/>
  </slot>
</openSlotList>

Каждый свободный час имеет URL, для выполнения действий над ним, в этом случае регистрация на этот час.

Пример: Регистрация на прием к доктору mjones с 14:00 до 14:50.

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
  <patient id = "jsmith"/>
</appointmentRequest>

HTTP/1.1 201 Created
Location: http://royalhope.nhs.uk/slots/1234/appointment
[various headers]

<appointment>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
  <link rel = "/linkrels/appointment/cancel"
        uri = "/slots/1234/appointment"/>
  <link rel = "/linkrels/appointment/addTest"
        uri = "/slots/1234/appointment/tests"/>
  <link rel = "self"
        uri = "/slots/1234/appointment"/>
  <link rel = "/linkrels/appointment/changeTime"
        uri = "/doctors/mjones/slots?date=20100104@status=open"/>
  <link rel = "/linkrels/appointment/updateContactInfo"
        uri = "/patients/jsmith/contactInfo"/>
  <link rel = "/linkrels/help"
        uri = "/help/appointment"/>
</appointment>

Преимуществом HATEOAS является то, что оно дает возможность разработчикам веб служб менять URI независимо от клиентов. Кроме этого, веб-сервис сам описывает себя без каких-либо WSDL. Чтобы правильно представить HATEOAS, представьте веб сайт из статических страниц. Вы открывайте главную страницу, а там уже ссылки на все остальное. Чтобы зайти на веб сайт и что-то найти там, нет необходимости прочитать какой-то документ по данному веб сайту, что-то вроде документа по API. Опять же, мое субъективное мнение по необходимости веб-сервиса поддерживать HATEOAS довольно пессимистично.

Если ваш сервис соответствует уровню 3, то его можно уже называть RESTful ну и конечно стариком с хорошим оптом.

Заключение

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

Поскольку второй случай более распространенный чем первый, приведу основные концепции:

  1. Веб-сервис – это один из методов реализации SOA архитектуры.
  2. Веб-сервис протоколом называется конкретная реализации веб-сервиса (XML-RPC, SOAP, JSON-RPC, и т.д.).
  3. REST является архитектурой, который был предложен в 2000 году и применялся для правильного создания компонентов веба и распределенных гипермедиа систем в целом.
  4. Вопрос чем отличается SOAP от REST, почти то же самое, что спросить, чем отличается бизон от хищника. SOAP-это протокол, у которого есть спецификация, а REST – это архитектура, которую можно применить для создания веб служб с использованием HTTP и URL.
  5. Richardson Maturity Model – это модель, предложенный Леонардом Ричардсоном для оценки зрелости веб службы. Понятия «ребенок», «подросток», «мужчина» и «старик» я сам ввел, чтобы более хорошо представить слоя модели RMM.

Будет ли веб служба ребенком или стариком – ваш выбор. Если вы или ваша компания разрабатывайте и серверную часть приложения и клиентскую, то думаю нет необходимости, чтобы ваша служба удовлетворяла всем пунктам RMM, особенно HATEOAS. «Мужчина» или «подросток» с этой задачей легко справятся. А если вы разрабатывайте что-то вроде amazon, у вас должны быть несколько тысяч клиентов, о которых вы понятия не имейте, то с этим наверное наилучшим образом справиться «старик». Если же ваша служба имеет очень мало функций, то дайте эту работу «ребенку», он знает, как все слить в одну кучу (в один ресурс).

Литература

1. www.oasis-open.org/committees/download.php/19679/soa-rm-cs.pdf
2. www.opengroup.org/standards/soa
3. www.w3.org/TR/ws-arch/#whatis
4. en.wikipedia.org/wiki/List_of_web_service_protocols
5. xmlrpc.scripting.com/spec.html
6. www.jsonrpc.org/specification
7. www.w3.org/TR/soap
8. www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf
9. restcookbook.com/Basics/hateoas
10. roy.gbiv.com/untangled/about
11. www.crummy.com/writing/speaking/2008-QCon/act3.html
12. martinfowler.com/articles/richardsonMaturityModel.html

Автор: TipTep

Источник

Поделиться

* - обязательные к заполнению поля