Краткое введение в ОТДЫХ

  1. Ключевые принципы REST
  2. Дайте каждой «вещи» удостоверение личности
  3. Связать вещи вместе
  4. Используйте стандартные методы
  5. Ресурсы с несколькими представлениями
  6. Общаться без гражданства
  7. ОТДЫХ в теории
  8. Резюме

Вы можете знать или не знать, что идет дискуссия о «правильном» способе реализации гетерогенного взаимодействия между приложениями: в то время как текущий основной поток явно фокусируется на веб-сервисах на основе SOAP, WSDL и юниверса спецификации WS- * небольшое, но очень громкое меньшинство утверждает, что есть лучший способ: REST, сокращение от REpresentational State Transfer. В этой статье я попытаюсь представить прагматичное введение в интеграцию REST и RESTful HTTP-приложений, не углубляясь в эту дискуссию. Я более подробно расскажу о тех аспектах, которые, по моему опыту, вызывают наибольшее обсуждение, когда кто-то впервые сталкивается с таким подходом.

Ключевые принципы REST

Большинство введений в REST начинаются с формального определения и фона. Я отложу это на некоторое время и приведу упрощенное, прагматичное определение: REST - это набор принципов, которые определяют, как должны использоваться веб-стандарты, такие как HTTP и URI (которые часто немного отличаются от того, что многие люди на самом деле). Обещание заключается в том, что если вы будете придерживаться принципов REST при разработке приложения, вы в конечном итоге получите систему, которая использует архитектуру Интернета в ваших интересах. Таким образом, пять ключевых принципов:

  • Дайте каждой «вещи» удостоверение личности
  • Связать вещи вместе
  • Используйте стандартные методы
  • Ресурсы с несколькими представлениями
  • Общаться без гражданства

Давайте подробнее рассмотрим каждый из этих принципов.

Дайте каждой «вещи» удостоверение личности

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

Основным преимуществом последовательной схемы именования вещей является то, что вам не нужно придумывать собственную схему - вы можете положиться на ту, которая уже была определена, работает довольно хорошо в глобальном масштабе и понятна практически любому. Если вы рассматриваете произвольный высокоуровневый объект в последнем приложении, которое вы создали (при условии, что оно не было создано RESTful-способом), вполне вероятно, что есть много вариантов использования, в которых вы бы получили выгоду от этого. Например, если ваше приложение содержит абстракцию клиента, я вполне уверен, что пользователям хотелось бы иметь возможность отправить ссылку конкретному клиенту по электронной почте коллеге, создать для него закладку в своем браузере или даже запишите это на листе бумаги. Вернемся к этому вопросу: представьте себе, какое ужасное деловое решение было бы, если бы интернет-магазин, такой как Amazon.com, не идентифицировал каждый из своих продуктов с уникальным идентификатором (URI).

Столкнувшись с этой идеей, многие люди задаются вопросом, означает ли это, что они должны выставлять свои записи в базе данных (или свои идентификаторы) напрямую - и часто потрясены одной лишь идеей, поскольку годы объектно-ориентированной практики говорят нам скрывать аспекты персистентности как деталь реализации. Но это вовсе не конфликт: обычно вещи - ресурсы, которые заслуживают идентификации с помощью URI, гораздо более абстрактны, чем запись в базе данных. Например, ресурс Order может состоять из элементов заказа, адреса и многих других аспектов, которые вы, возможно, не захотите выставлять как индивидуально идентифицируемые ресурсы. Принятие идеи идентификации всего, что стоит идентифицировать, приводит к созданию ресурсов, которые вы обычно не видите в типичном дизайне приложения: шаг процесса или процесса, продажа, переговоры, запрос предложения - эти все примеры «вещей», которые заслуживают идентификации. Это, в свою очередь, может привести к созданию более постоянных объектов, чем в не-RESTful дизайне.

Вот несколько примеров URI, которые вы можете придумать:

http://example.com/customers/1234 http://example.com/orders/2007/10/776654 http://example.com/products/4554 http://example.com/processes/salary-increase -234

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

http://example.com/orders/2007/11 http://example.com/products?color=green

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

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

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

Связать вещи вместе

Следующий принцип, который мы рассмотрим, имеет формальное описание, которое немного пугает: «Гипермедиа как движок состояния приложения», иногда сокращенно обозначаемое как HATEOAS. (Серьезно - я не придумываю это.) В его основе лежит концепция гипермедиа , или другими словами: идея ссылок . Ссылки - это то, с чем мы все знакомы по HTML, но они никоим образом не ограничены потреблением человеком. Рассмотрим следующий готовый фрагмент XML:

<order self = 'http: //example.com/customers/1234'> <amount> 23 </ amount> <product ref = 'http: //example.com/products/4554' /> <customer ref = ' http://example.com/customers/1234 '/> </ order>

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

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

Чтобы суммировать эти принципы: Используйте ссылки, чтобы ссылаться на идентифицируемые вещи (ресурсы), где это возможно. Гиперссылки - это то, что делает Интернет сетью.

Используйте стандартные методы

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

Он знает, что с ним делать, потому что каждый ресурс поддерживает один и тот же интерфейс, один и тот же набор методов (или операций, если вы предпочитаете). HTTP вызывает эти глаголы , и в дополнение к двум всем известным (GET и POST) набор стандартных методов включает в себя PUT, DELETE, HEAD и OPTIONS. Смысл этих методов определен в спецификации HTTP вместе с некоторыми гарантиями их поведения. Если вы являетесь разработчиком OO, вы можете представить, что каждый ресурс в сценарии RESTful HTTP расширяет класс, подобный этому (в некотором псевдосинтаксисе в стиле Java / C # и концентрируясь на ключевых методах):

class Resource {Resource (URI u); Ответ get (); Ответный пост (запрос р); Ответ поставлен (Запрос р); Удалить ответ (); }

Поскольку один и тот же интерфейс используется для каждого ресурса, вы можете рассчитывать на то, что сможете получить представление - то есть его рендеринг - используя GET. Поскольку семантика GET определена в спецификации, вы можете быть уверены, что у вас нет обязательств, когда вы ее вызываете - вот почему метод называется «безопасный». GET поддерживает очень эффективное и сложное кэширование, поэтому во многих случаях вам даже не нужно отправлять запрос на сервер. Вы также можете быть уверены, что GET является идемпотентом - если вы отправляете запрос GET и не получаете результата, вы можете не знать, достиг ли ваш запрос своего назначения, или ответ был утерян на обратном пути к вам. Гарантия идемпотентности означает, что вы можете просто отправить запрос еще раз. Идемпотентность также гарантируется для PUT (что в основном означает «обновить этот ресурс этими данными или создать его по этому URI, если его там еще нет») и для DELETE (которую вы можете просто попробовать снова и снова, пока не получите результат - удаление то, чего нет, не проблема). POST, который обычно означает «создать новый ресурс», также может использоваться для вызова произвольной обработки и, следовательно, не является ни безопасным, ни идемпотентным.

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

Рассмотрим следующий пример простого сценария закупок:

Рассмотрим следующий пример простого сценария закупок:

Вы можете видеть, что здесь определены две службы (без какой-либо конкретной технологии реализации). Интерфейс этих сервисов специфичен для данной задачи - это сервис OrderManagement и CustomerManagement, о котором мы говорим. Если клиент хочет использовать эти сервисы, он должен быть закодирован в соответствии с этим конкретным интерфейсом - невозможно использовать клиент, созданный до того, как были определены эти интерфейсы, для осмысленного взаимодействия с ними. Интерфейсы определяют протокол приложения услуг.

В подходе RESTful HTTP вам придется обойтись с универсальным интерфейсом, который составляет протокол приложения HTTP . Вы можете придумать что-то вроде этого:

Вы можете видеть, что определенные операции службы были сопоставлены со стандартными методами HTTP - и для устранения неоднозначности я создал целую вселенную новых ресурсов. «Это обман!», Я слышу, как ты плачешь. Нет, это не так. GET для URI, который идентифицирует клиента, так же значим, как и операция getCustomerDetails. Некоторые люди использовали треугольник, чтобы визуализировать это:

Представьте три вершины как ручки, которые вы можете повернуть. Вы можете видеть, что в первом подходе у вас есть много операций и много видов данных и фиксированное количество «экземпляров» (по сути, столько же, сколько у вас есть сервисов). Во втором случае у вас есть фиксированное количество операций, много видов данных и множество объектов для вызова этих фиксированных методов. Смысл этого в том, чтобы проиллюстрировать, что вы можете в основном выразить все, что вам нравится, с обоими подходами.

Почему это важно? По сути, это делает ваше приложение частью Интернета - его вклад в то, что превратило Интернет в самое успешное приложение Интернета, пропорционален количеству ресурсов, которые оно добавляет к нему. В подходе RESTful приложение может добавить несколько миллионов пользовательских URI в Интернет; если он спроектирован так же, как приложения были спроектированы во времена CORBA, его вклад, как правило, представляет собой единую «конечную точку» - сравнимую с очень маленькой дверью, которая обеспечивает доступ к юниверсу ресурсов только для тех, у кого есть ключ.

Унифицированный интерфейс также позволяет каждому компоненту, который понимает протокол приложения HTTP, взаимодействовать с вашим приложением. Примерами компонентов, которые выигрывают от этого, являются универсальные клиенты, такие как curl и wget, прокси, кеши, HTTP-серверы, шлюзы, даже Google / Yahoo! / MSN и многие другие.

Подводя итог: Чтобы клиенты могли взаимодействовать с вашими ресурсами, они должны правильно реализовывать протокол приложений по умолчанию (HTTP), то есть использовать стандартные методы GET, PUT, POST, DELETE.

Ресурсы с несколькими представлениями

До сих пор мы игнорировали небольшое осложнение: как клиент узнает, как обращаться с данными, которые он получает, например, в результате запроса GET или POST? Подход, используемый HTTP, заключается в том, чтобы разделить проблемы между обработкой данных и вызовом операций. Другими словами, клиент, который знает, как обрабатывать определенный формат данных, может взаимодействовать со всеми ресурсами, которые могут обеспечить представление в этом формате. Давайте снова проиллюстрируем это на примере. Используя согласование содержимого HTTP, клиент может запросить представление в определенном формате:

GET / Customers / 1234 HTTP / 1.1 Хост: example.com Принять: application / vnd.mycompany.customer + xml

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

GET / Customers / 1234 HTTP / 1.1 Хост: example.com Принять: text / x-vcard

Результатом может быть адрес клиента в формате VCard. (Я не показал ответы, которые содержали бы метаданные о типе данных в заголовке HTTP Content-type.) Это показывает, почему в идеале представления ресурса должны быть в стандартных форматах - если клиент «знает» оба Протокол приложения HTTP и набор форматов данных, он может взаимодействовать с любым приложением RESTful HTTP в мире очень значимым образом. К сожалению, у нас нет стандартных форматов для всего, но вы, вероятно, можете себе представить, как можно создать меньшую экосистему внутри компании или группы сотрудничающих партнеров, полагаясь на стандартные форматы. Конечно, все это относится не только к данным, отправляемым с сервера клиенту, но и к обратному направлению - сервер, который может принимать данные в определенных форматах, не заботится о конкретном типе клиента, если он следует протокол приложения.

Есть еще одно существенное преимущество практического использования нескольких представлений ресурса: если вы предоставляете представление ресурсов как в формате HTML, так и в формате XML, они могут использоваться не только вашим приложением, но и каждым стандартным веб-браузером - другими словами, Информация в вашем приложении становится доступной каждому, кто знает, как пользоваться Интернетом.

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

Резюме: обеспечить несколько представлений ресурсов для различных нужд.

Общаться без гражданства

Последний принцип, к которому я хочу обратиться, - это общение без гражданства . Прежде всего, важно подчеркнуть, что, хотя REST включает в себя идею безгражданства, это не означает, что приложение, которое демонстрирует свое функциональное состояние, не может иметь состояния - фактически, это сделало бы весь подход довольно бесполезным в большинстве сценариев. REST требует, чтобы это состояние было либо переведено в состояние ресурса, либо сохранено на клиенте. Другими словами, сервер не должен сохранять какое-либо состояние связи для любого из клиентов, с которыми он связывается, кроме одного запроса. Наиболее очевидной причиной этого является масштабируемость - количество взаимодействующих клиентов может серьезно повлиять на объем работы сервера, если он должен будет поддерживать состояние клиента. (Обратите внимание, что это обычно требует некоторой доработки - вы не можете просто привязать URI к некоторому состоянию сеанса и назвать его RESTful.)

Но есть и другие аспекты, которые могут быть гораздо важнее: ограничение без сохранения состояния изолирует клиента от изменений на сервере, поскольку он не зависит от обращения к одному и тому же серверу в двух последовательных запросах. Клиент может получить документ, содержащий ссылки с сервера, и хотя он выполняет некоторую обработку, сервер может быть выключен, его жесткий диск может быть извлечен и заменен, программное обеспечение может быть обновлено и перезапущено - и если клиент следует одну из ссылок, полученных с сервера, он не заметит.

ОТДЫХ в теории

Я должен сделать признание: то, что я объяснил, на самом деле не ОТДЫХ, и я мог бы огорчиться из-за упрощения вещей слишком много. Но я хотел начать все немного иначе, чем обычно, поэтому вначале я не предоставлял формального фона и истории REST. Позвольте мне попытаться ответить на этот вопрос, если несколько кратко.

Прежде всего, я старался не отдавать REST от самого HTTP и использовать HTTP RESTful. Чтобы понять взаимосвязь между этими различными аспектами, мы должны взглянуть на историю REST.

Термин REST был определен Рой Т. Филдинг в его Кандидатская диссертация (Вы могли бы действительно хотеть перейти по этой ссылке - это вполне читабельно, по крайней мере, для диссертации). Рой был одним из главных разработчиков многих основных веб-протоколов, включая HTTP и URI, и он формализовал многие идеи, стоящие за ними в документе. (Диссертация считается «библией ОТДЫХА», и по праву так - в конце концов, автор придумал этот термин, поэтому по определению все, что он написал о нем, следует считать авторским.) В диссертации Рой сначала определяет методологию для разговора. об архитектурных стилях - абстрактные шаблоны высокого уровня, которые выражают основные идеи, лежащие в основе архитектурного подхода. Каждый архитектурный стиль имеет набор ограничений, которые его определяют. Примеры архитектурных стилей включают «нулевой стиль» (который вообще не имеет ограничений), канал и фильтр, клиент / сервер, распределенные объекты и - как вы уже догадались - REST.

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

Одним «воплощением» стиля REST является HTTP (и набор связанных наборов стандартов, таких как URI), или чуть более абстрактно: сама архитектура Web. Чтобы продолжить приведенный выше пример, HTTP «создает» единый интерфейс REST с конкретным интерфейсом, состоящим из глаголов HTTP. Поскольку Филдинг определил стиль REST после того, как Интернет - или, по крайней мере, большая его часть - уже был «готов», можно спорить, соответствует ли он на 100%. Но в любом случае, Web, HTTP и URI являются единственным основным, безусловно, единственным релевантным экземпляром стиля REST в целом. И поскольку Рой Филдинг является одновременно автором диссертации REST и оказал сильное влияние на дизайн веб-архитектуры, это не должно вызывать удивления.

Наконец, время от времени я использовал термин «RESTful HTTP» по простой причине: многие приложения, использующие HTTP, не следуют принципам REST - и с некоторым обоснованием можно сказать, что использование HTTP без соблюдения Принципы REST равны злоупотреблению HTTP. Конечно, это звучит немного усердно - и на самом деле часто есть причины, по которым можно нарушить ограничение REST, просто потому, что каждое ограничение вызывает некоторый компромисс, который может быть неприемлемым в конкретной ситуации. Но часто ограничения REST нарушаются из-за простого непонимания их преимуществ. Чтобы привести один особенно неприятный пример: использование HTTP GET для вызова таких операций, как удаление объекта, нарушает ограничение безопасности REST и здравый смысл (клиент не может быть привлечен к ответственности, что, вероятно, не то, что разработчик сервера намеревался). Но об этом и других заметных злоупотреблениях читайте в следующей статье.

Резюме

В этой статье я попытался дать краткое представление об основах REST - архитектуре Интернета. Подход RESTful HTTP для предоставления функциональности отличается от RPC, распределенных объектов и веб-служб; требуется некоторое изменение сознания, чтобы действительно понять эту разницу. Знание принципов REST полезно, если вы создаете приложения, которые предоставляют только веб-интерфейс, или хотите превратить API своего приложения в хорошего веб-пользователя.

Стефан Тилков является ведущим редактором SOA-сообщества InfoQ и соучредителем, главным консультантом и ведущим RESTafarian в Германии / Швейцарии. innoQ ,

Будьте в курсе тенденций в отрасли с одним ежемесячная новостная рассылка , написанный архитекторами для архитекторов.

Com/products?
Если вы видите URI, написанный на боковой стороне шины, вы можете ввести его в поле адреса вашего браузера и нажать клавишу возврата - но как ваш браузер узнает, что делать с URI?
Почему это важно?