Введение
Четыре года назад я написал свою первую статью на Хабре и она была посвящена созданию RESTful web API на платформе InterSystems. С тех пор прошло немало времени и вышло несколько новых релизов, которые значительно упростили работу по созданию RESTful web API. Вот об этих изменениях я и хочу рассказать в этой статье, а также дать несколько советов по созданию RESTful web API на платформе InterSystems.
Содержание
- Архитектура RESTful web API
- Брокеры
- Разделение брокеров
- Параметры брокеров
- Обобщение кода
- CORS
- Аутентификация
- Инструменты отладки и тестирования
- Примеры
- JSON
- Выводы
- Ссылки
Архитектура RESTful web API
Надеюсь, что читатель знаком с тем что такое RESTful web API и основами его реализации на платформе InterSystems (доступно начиная с версии 2014.1). Этому посвящено много статей/вебинаров/обучающих курсов в частности и моя предыдущая статья. В любом случае первое с чего хотелось бы начать это общая высокоуровневая архитектура вашего приложения, включающего RESTful web API. Выглядеть она может следующим образом:
На этой схеме представлены основные уровни вашего решения:
Данные
Хранимые классы на платформе InterSystems.
Терминальное API
Слой взаимодействия с данными. Данные не должны изменяться иначе, чем через это API.
Методы этого API не пишут на устройство. Терминальное API может возвращать:
- Объект
- Статус или исключение (в зависимости от ваших предпочтений)
Web API
Преобразует входящий запрос в форму, понимаемую терминальным API и вызывает методы терминального API. Результата выполнения терминального API возвращаются клиенту.
Web API не взаимодействует с данными напрямую. Употребляю термин Web API а не RESTful web API, т.к. Web API может быть реализовано с применением иной архитектуры, например на основе протокола WebSocket который также поддерживается платформой InterSystems, о чём уже писали на Хабре и не раз.
Клиент
Как правило JavaScript (но совсем необязательно) приложение доступное конечному пользователю. Этот уровень не должен иметь прямых связей с базой данных, быть нагруженным основной бизнес-логикой и хранить состояние приложения. На этот уровень обычно выносится только простейшая бизнес-логика: интерфейс авторизации, проверка вводимых значений на допустимость и соответствие формату, несложные операции с данными (сортировка, группировка, подсчёт значений), уже загруженными на клиент.
Подобное разделение увеличивает конфигурируемость приложения, облегчает его отладку, поиск и исправление ошибок. По сути это трёхуровневая архитектура построения приложений.
Брокеры
Брокеры это классы, содержащие логику вашего RESTful web API. Они:
- Наследуются от
%CSP.REST
- Содержит пути – сопоставления URI и вызываемых методов
Пример пути:
<Route
Url="/path/:param1/:param2"
Method="GET"
Call="Package.Class:ClassMethod"
/>
Где ClassMethod
– любой метод класса.
Разделение брокеров
«Физическое» разделение
Так как в RESTful web API может быть много путей — методов, один брокер скоро будет перегружен методами. Чтобы этого не произошло разделяйте брокеры на несколько классов следующим образом:
Где:
- Абстрактный брокер отвечает за преобразование запросов, CORS и прочие технические моменты не связанные с логикой RESTful web API.
- Брокеры 1..N собственно содержит методы, обрабатывающие запросы (вызывающие методы терминального API и возвращающие ответы терминального API клиенту).
«Логическое» разделение и версионирование
Обычно Брокеры содержит пути – сопоставления URI и вызываемых методов, но кроме путей брокеры могут «передавать» запросы друг другу. Выглядит это так:
<Map Prefix="/form" Forward="Destination.Broker"/>
Это позволяет провести разделение брокеров по предметным областям с которыми они связаны, а также обеспечить версионирование API:
Параметры брокеров
Вот параметры которые рекомендуется установить в брокерах вашего RESTful web API:
Parameter CONTENTTYPE = {..#CONTENTTYPEJSON};
Parameter CHARSET = "UTF-8";
Parameter UseSession As BOOLEAN = 1;
Вот за что они отвечают:
- CONTENTTYPE — добавляет во все ответы сервера информацию о том, что ответ будет в формате JSON.
- CHARSET — конвертирует ответ в формат UTF8.
- UseSession — использует сессию для запросов пользователя. Подробнее об этом в разделе аутентификация.
Так как все брокеры наследуются от одного абстрактного брокера, то эти параметры достаточно указать один раз в абстрактном брокере (наследуются только параметры первого суперкласса).
Обобщение кода
Одна из проблем, часто возникающих при написании RESTful web API это копипаста кода из брокера в брокер, что создаёт большое число путей и строк кода. Для избежания этого рекомендую использовать кодогенерацию совместно с пакетом %Dictionary содержащим всю метаинформацию необходимую для написания метод-генераторов. Примером активного использования кодогенерации является библиотека RESTForms. Кроме того использование кодогенерации позволяет достичь большего единообразия вашего RESTful web API.
CORS
Технология современных браузеров, которая позволяет предоставить веб-странице доступ к ресурсам другого домена. Для включения доступа к вашему RESTful web API с использованием CORS добавьте в брокер параметр:
Parameter HandleCorsRequest = 1;
Что предоставит доступ с любого другого домена. Это небезопасно и поэтому надо также переопределить метод OnHandleCorsRequest
, его сигнатура:
ClassMethod OnHandleCorsRequest(pUrl As %String) As %Status {}
Этот метод должен проверять Origin запроса, к примеру он должен совпадать с именем хоста веб-приложения. Для получения Origin можно использовать вот такой метод:
ClassMethod GetOrigins() As %String
{
set url = %request.GetCgiEnv("HTTP_REFERER")
return $p(url,"/",1,3) // get http(s)://origin.com:port
}
Аутентификация
Для того чтобы один пользователь потреблял одну лицензию и работал в рамках одной сессии нужно сконфигурировать в Портале Управления Системой ваши REST и CSP приложения так, чтобы выполнялись условия:
- Во всех брокерах
Parameter UseSession = 1;
. - Все веб приложения доступны только с аутентификацией.
- У всех веб приложений установлен таймаут сессии (900, 3600).
- У всех приложений установлено одно значение
GroupById
. - У всех приложений установлено одно значение
Cookie Path
.
Инструменты отладки и тестирования
Для отладки можно использовать такие внешние средства как:
- REST клиент (например Postman) — первоочередной инструмент отладки RESTful web API позволяет сохранять и документировать запросы, форматировать JSON ответы, выполнять запросы к нескольким окружениям и предоставляет многие другие удобства для разработчика.
- Перехватывающий прокси-сервер (например Fiddler) — позволяет перехватывать, отображать, редактировать и дублировать запросы к RESTful web API.
- Анализатор трафика (например WireShark) — помогает в случаях битых пакетов, проблем с кодировками, необходимостью анализа удалённой системы и прочими ситуациями когда вышеназванных инструментов недостаточно.
Настоятельно не рекомендую использовать инструменты командной строки, такие как curl и wget.
Подробно внешние и внутренние средства отладки описаны в серии статей (Часть 1 — внешние средства, Часть 2 — внутренние средства) на InterSystems Developer Community.
Примеры
Приведу несколько примеров RESTful web API.
MDX2JSON и клиент DeepSeeWeb
MDX2JSON — RESTful web API предоставляет информацию о кубах, пивотах, дашбордах и многих других элементах DeepSee, в частности — результатах исполнения MDX запросов, что позволяет встраивать пользовательский интерфейс аналитического решения на DeepSee в любое современное Web или мобильное приложение. Работает начиная с версии 2014.1.
DeepSeeWeb — AngularJS приложение, предоставляющее альтернативную реализацию портала пользователя DeepSee. Может быть легко кастомизирован. Использует MDX2JSON в качестве бэкэнда. Вот пример дашборда визуализированного в DeepSeeWeb:
Подробная статья про DeepSee.
EnsembleWorkflow и клиент EnsembleWorkflowUI
В интеграционной платформе InterSystems есть подсистема Ensemble Workflow, позволяющая людям участвовать в автоматизированных бизнес-процессах. Ensemble Workflow RESTful web API и клиент EnsembleWorkflowUI. RESTful web API предоставляет доступ к задачам пользователя. Работает начиная с версии 2014.1. Вот так выглядит визуализация:
RESTForms
RESTForms — универсальный RESTful web API бэкэнд работы с данными на платформе InterSystems 2016.1+ для современных веб-приложений.
Вот часть путей, доступных в RESTForms:
URL | Описание |
---|---|
info | Список классов |
info/all | Метаинформация всех классов |
info/:class | Метаинформация одного класса |
object/:class/:id | Получить объект |
object/:class/:id/:property | Получить свойство объекта |
object/:class | Создать объект |
object/:class/:id | Обновить объект из динамического объекта |
object/:class | Обновить объект из объекта класса |
object/:class/:id | Удалить объект |
objects/:class/:query | Выполнить SQL запрос |
В этом проекте активно используется обобщение кода (с помощью кодогенерации и использования пакета %Dictionary
).
Доступны клиенты на Angular и React, выглядит это так:
JSON
JavaScript Object Notation — текстовый формат обмена данными, использующийся совместно с RESTful web API. Поддержка JSON на платформе InterSystems появилась начиная с версии 2009.2, но была значительно улучшена к версии 2016.2. Подробнее об использовании JSON можно почитать в документации.
Выводы
- REST на сегодня – основная и общепринятая методика построения API для сети интернет
- Предоставляя RESTful web API вы получаете возможность выбора из огромного набора технологий построения клиентских приложений, в том числе:
- JavaScript (AngularJS, React, extJS, ...)
- Мобильные приложения (Cordova и подобные, Native)
- Технологии InterSystems позволяют вам с лёгкостью создавать RESTful web API.