2009-08-04 7 views
3

У меня есть довольно простой вопрос о внедрении клиента доступа к данным, который строго придерживается архитектурных принципов REST. Для начала предположим, что у меня есть хороший REST API, который я хочу использовать с помощью приложения Django. Начну, обнаруживая, что услуги предоставляются (отредактированный для наблюдения):Взаимодействие с клиентами RESTful

GET example.com/services/ HTTP/1.1 

HTTP/1.1 200 OK 
<?xml version="1.0" encoding="UTF-8"?> 
<services> 
    <service> 
    <name>Widgets</name> 
    <link>http://example.com/services/widgets/</link> 
    <item_link>http://example.com/services/widgets/{widget_id}/</item_link> 
    </service> 
    <service> 
    <name>Factories</name> 
    <link>http://example.com/services/factories/</link> 
    <item_link>http://example.com/services/factories/{factory_id}/</item_link> 
    </service> 
    ... 
</services> 

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

def get_service(request, service_name): 
    doc = etree.parse(urllib.urlopen('http://example.com/services/')) 
    uri = doc.xpath("service/name[.='%s']/following-sibling::*" % service_name)[0].text 
    ... 

От которого я выполнить другой запрос (отредактированный для наблюдения):

GET example.com/services/widgets/ HTTP/1.1 

HTTP/1.1 200 OK 
<?xml version="1.0" encoding="UTF-8"?> 
<widgets> 
    <item_link>http://example.com/services/widgets/{widget_id}/</item_link> 
    <widget> 
    <id>1</id> 
    <name>Whizbang Foobar</name> 
    <link>http://example.com/services/widgets/1</link> 
    </widget> 
    ... 
</widgets> 

Теперь я отобразить простой список виджетов в обработанном шаблоне Django. Отсюда, как, как я продолжаю взаимодействовать с этим сервисом RESTfully? Возможно, я запутался в замешательстве, но единственное, что я могу придумать, - это реализовать множество представлений приложений или тонкую модель данных Django, чтобы сохранить URI службы.

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

Приносим извинения за длину и многословие вопроса и неизбежное выражение лица изуродованных читателей.

Последующая деятельность:

Является ли следующий правильный путь (используя шаблоны URI) реализации этих взаимодействий? Для демонстрационных целей (вместо более абстрактной реализации), другой вид Django, чтобы получить элемент коллекции ресурсов:

def get_item(request, service_name, item_id): 
    doc = etree.parse(urllib.urlopen('http://example.com/services/')) 
    uri = doc.xpath("service/name[.='%s']/following-sibling::item_link" % service_name)[0].text 
    ... 

Тогда последующий запрос:

GET example.com/services/widgets/1 HTTP/1.1 

HTTP/1.1 200 OK 
<?xml version="1.0" encoding="UTF-8"?> 
<widget> 
    <id>1</id> 
    <name>Whizbang Foobar</name> 
    <tags>foo bar baz ham eggs</tags> 
    <index_link>http://example.com/services/widgets/</index_link> 
</widget> 

ответ

3

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

Лучший пример, который я смог найти, это Sun Cloud API. В большей части документации описываются различные типы носителей, используемые системой, которая, по-видимому, является ключом к вытаскиванию такого рода вещей.

Я нахожу, что это помогает писать своего клиента одновременно с разработкой вашего API. Таким образом, вы можете определить, что может привести к тому, что ваш API станет причиной недостатка кода, и устранить проблему.

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

Например, вы можете определить тип носителя «Индекс», который просто перечисляет связанные ресурсы. Индекс определяет ссылки для разбивки на страницы, получение элементов в списке, поиск предметов по названию и т. Д.

Затем вы можете определить базовый тип носителя, называемый «Item». Элемент имеет ссылку для отображения родительского индекса, обновления/удаления самого себя и т. Д. Ваш вид Widget может быть представлен двумя разными типами носителей: одним индексом и одним, основанным на элементе.

Вы можете начать с реализации одного класса, который обрабатывает тип носителя Index. Затем вы можете написать базовый класс, который будет обрабатывать все обычные действия типа Media. Наконец, вы можете написать клиент Widget, который обрабатывает все поведение, зависящее от виджета, и которое расширяет клиент Item. Эти клиенты могли бы раскрывать свою функциональность (доступность большего количества ссылок и полей данных) идиоматическим способом для языка, на котором они были написаны.

Обработка ответа с вашего сервера тогда будет вопросом соответствия типу mime ответ на одного из клиентов, которые вы написали.

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

+0

Спасибо за этот четкий ответ. Облачный API и его ориентация на типы медиа значительно улучшили мое понимание. В качестве продолжения использовались бы шаблоны URI в медиаресурсе «Индекс» ресурса как правильный способ обнаружения «элементов» ресурса (см. Редактирование вопросов и последующее наблюдение)? – user150093

+0

Возможно, хотя я не уверен, что это необходимо. Как насчет того, чтобы указать тип носителя Index, который включает (разбитый на страницы) список ссылок на объекты? Ссылки для разбивки на страницы, так же как и с HTML-представлением, могут использоваться для направления клиента через список «Элементы». –

+0

@ m0nikr: обычно это не стоит, потому что браузеры все равно используют сжатие gzip, что сделает ненужным оптимизацию на этом уровне. Просто включите полные URI. – aehlke

1

Если я правильно понимаю ваш вопрос, вы хотите исследовать неизвестную услугу, правильно?

Если да, то вы можете, например, продолжить запрос OPTIONS к ресурсу «виджетов», чтобы узнать, какие методы HTTP он поддерживает (они должны быть указаны в заголовке ответа Allow).
Затем вы можете сделать то же самое для всех URI, найденных в <link rel="whatever"> элементах. Если ресурс, найденный таким образом, указывает, что он поддерживает GET, затем извлекайте его и повторите ...
Таким образом, вы сможете исследовать все вложенные ресурсы.

Этот вид исследования будет, конечно, получить только вы до сих пор, потому что на самом деле взаимодействовать с услугой, вам нужно будет знать о его типах носителей (или представлений), и то, что различные <link rel="whatever"> действия, которые вы нашли на самом деле имею в виду. Этот шаг не может быть автоматизирован, вам нужно будет прочитать документацию для службы и построить свой клиент соответственно. Я предлагаю прочитать статью «How to GET a Cup of Coffee», которая, как мне кажется, очень хорошо объясняет это взаимодействие.

1

Sun Cloud API документация - отличный пример API RESTful, ориентированный на типы медиа.

3

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

Часто я вижу людей, пытающихся использовать интерфейсы REST как своего рода уровень доступа к данным на основе HTTP.С этой ментальной моделью гиперссылки данных обеспечивают не более, чем структурные отношения данных. Трудно построить поведение приложения поверх этого интерфейса, не нарушая ограничений RESTful.

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

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

При написании клиента для интерфейса REST мне представляется полезным представить себе, что я пишу пользовательский веб-браузер, который понимает только те типы мультимедиа, которые поставляются этим интерфейсом RESTful и жестко закодирован для запуска по определенному URL-адресу и нет адресной строки!

+0

У меня было такое чувство. Я знаю, что я мог бы написать клиенту поставляемый веб-интерфейс с использованием XSLT (предполагая типы XML-mime), но каков правильный способ делать вещи, если я хочу, чтобы удаленное приложение вызывало клиента REST? Скажем, у меня есть проект Django с несколькими приложениями, которые взаимодействуют по-разному. Я хочу создать другое приложение, которое взаимодействует (или вызывает взаимодействия с клиентом) с заданным REST API. Каков наилучший способ реализации этого при сохранении логики приложения и взаимодействия с пользователем в приложении Django - или это потерянная причина? – user150093

+2

Нет, это не потерянное дело. Просто признайте, что ваша часть вашего приложения Django должна действовать как агент очистки экрана для этого REST api. Этот агент будет эффективно иметь собственное состояние приложения, которому необходимо управлять. В некотором смысле ваше приложение должно действовать таким образом, который аналогичен тому, как javascript взаимодействует с веб-браузером и DOM. –

Смежные вопросы