Naumen Serviсe Desk 4.3 Использование RESTful сервисов АННОТАЦИЯ Настоящий документ представляет собой руководство по использованию REST сервисов в программном продукте Naumen Service Desk. Документ рассчитан на пользователя, обладающего уверенными навыками работы с компьютером и веб-интерфейсом, обладающего навыками работы c интерфейсом программирования приложений (API). Руководство содержит описание использования REST сервисов с примерами. Комментарии к документу: Версия Naumen Service Desk 4.3.3 Если вы хотите отправить замечание или предложение по содержанию документов, напишите нам письмо по адресу: docs@naumen.ru Copyright© 2003-2014, NAUMEN. Все права защищены. Никакая часть этого документа не может быть воспроизведена или обработана в системах обработки данных, скопирована или использована в других документах без письменного уведомления компании NAUMEN. Информация, содержащаяся в этом документе, может быть изменена компанией NAUMEN без предварительного уведомления. Компания NAUMEN не гарантирует отсутствия ошибок или опечаток в этом документе. Naumen Service Desk является зарегистрированной торговой маркой компании NAUMEN. Остальные торговые марки являются зарегистрированными торговыми марками их владельцев. -2- СОДЕРЖАНИЕ Глава 1 - Общие сведения об архитектуре REST 5 Глава 2 - REST API 6 2.1 Адрес для выполнения методов 6 2.2 Генерация ключей авторизации для выполнения действий через REST сервисы 6 2.3 Формирование ссылок для работы с собственными RESTful сервисами 7 2.4 Методы REST API 8 Глава 3 - Логирование REST 13 -3- УСЛОВНЫЕ ОБОЗНАЧЕНИЯ, ПРИНЯТЫЕ В ДОКУМЕНТЕ В настоящем руководстве используются условные обозначения: — особенности выполнения действия/настройки, влекущие значимые последствия для работы системы. — особенности выполнения действия/настройки, упрощающие работу в системе, но не влекущие значимых последствий. — влияние прав доступа на возможности пользователя при выполнении действий. — пример. В настоящем документе приняты следующие соглашения: l l l "жирным шрифтом" выделяются названия кнопок, вкладок, полей и других элементов пользовательского интерфейса системы. курсивом выделяется пример текста при заполнении полей ввода на формах добавления и редактирования; также пример текста экранных сообщений. выполняемые команды и фрагменты скриптов выделены цветом и фоном. -4- Глава 1 - Общие сведения об архитектуре REST Глава 1 - Общие сведения об архитектуре REST REST (Representational State Transfer) — стиль построения архитектуры распределенного приложения. REST был описан и популяризован Роем Филдингом (Roy Fielding) в 2000 году, одним из создателей протокола HTTP. Самой известной системой, построенной в значительной степени по архитектуре REST, является современная Всемирная паутина (World Wide Web). Данные в REST передаются в виде небольшого количества стандартных форматов, например, HTML, XML, JSON. Сетевой протокол, как и HTTP, должен поддерживать кэширование, не зависеть от сетевого слоя и удалять информацию о состоянии между парами «запрос-ответ». Такой подход обеспечивает масштабируемость системы и позволяет ей эволюционировать с новыми требованиями. Обращение к серверу происходит по протоколу HTTP 1.1. В зависимости от требуемых операций используются различные методы обращения. Операция Метод обращения Создание объектов GET, POST Редактирование объекта Получение объекта, списка объектов Удаление объекта Выполнение скриптов Прикрепление файла GET, PUT, POST GET GET, POST, DELETE POST POST -5- Глава 2 - REST API Глава 2 - REST API Для корректной работы REST API при установке системы необходимо указать кодировку "UTF-8", см. "Руководство системного администратора, раздел "Установка Apache Tomcat". При формировании строки вызова метода REST API вручную, нужно обратить особое внимание на то, что строка должна соответствовать требованиям для URL (www.w3schools.com). Все не ASCII символы должны быть закодированы в ASCII для корректной передачи данных через браузер на сервер. Особое внимание нужно обратить на кодирование символа "/" используемого в именах параметров или в значениях параметров, который должен быть закодирован в "%2F". 2.1 Адрес для выполнения методов <URL> + '/services/rest/' + <method> + '?accessKey='+<accessKey>, где: l l l <URL> — адрес приложения, например, http://127.0.0.1:8080/sd; <method> — часть адреса, идентифицирующая выполняемый метод, см. "Методы REST API" (стр.8); <accessKey> — ключ доступа, см. "Генерация ключей авторизации для выполнения действий через REST сервисы" (стр.6). Например, можно обращаться по ссылкам: http://127.0.0.1:8080/sd/services/rest/create/currency/?accessKey=cd9fd8c6-5d53-49c1a1b1-706c781d8966&title=Франк&code=frank http://127.0.0.1:8080/sd/services/rest/create/serviceCall?accessKey=cd9fd8c6-5d53-49c1a1b1-706c781d8966 2.2 Генерация ключей авторизации для выполнения действий через REST сервисы Для выполнения действий через REST сервисы может указываться ключ авторизации, под которым будет выполняться операция — "accessKey". По умолчанию генерируется многоразовый ключ с возможностью использования в течении одной недели. api.auth.getAccessKey('username') — ключ авторизации для пользователя с логином username на одну неделю от текущего момента. Методы генерации многоразовых и одноразовых ключей: api.auth.getAccessKey('username').setDisposable() //одноразовый api.auth.getAccessKey('username').setReusable() //многоразовый Методы для задания времени жизни ключа: api.auth.getAccessKey('username').setDeadlineDays(days); api.auth.getAccessKey('username').setDeadlineHours(hours); api.auth.getAccessKey('username').setDeadlineMinutes(minutes); Особенности работы ключа авторизации. Если пользователь, уже авторизованный в системе, получает ссылку на выполнение действия с ключом авторизации другого пользователя, то при переходе по ссылке действие выполнится от лица пользователя, указанного в ключе, а пользователь продолжит работу в системе под своей учетной записью. Чтобы получить ключ авторизации, выполните следующие действия: -6- Глава 2 - REST API 1. Напишите скрипт и сохраните его в файл, например, getAccessKey.groovy. Для пользователя "username": return api.auth.getAccessKey('username').uuid 2. Выполните скрипт через консоль приложения Naumen ServiceDesk 4.0. Ключ доступа можно получить только из консоли. 3. Запомните результат выполнения скрипта, полученное значение вводится без пробелов. cd9fd8c6-5d53-49c1-a1b1-706c781d8966 2.3 Формирование ссылок для работы с собственными RESTful сервисами api.rest — методы скриптового API формирования ссылок для выполнения бизнес-операции через RESTful-сервисы приложения: l l l l l api.rest.get(obj) — формирует ссылку для получения объекта, где obj — существующий объект системы api.rest.find(fqn, attributes) — формирует ссылку для поиска объектов api.rest.edit(obj, attributes) — формирует ссылку для редактирования объекта api.rest.delete(obj) — формирует ссылку для удаления объекта api.rest.create(fqn, attributes) — формирует ссылку для создания объекта Файлы со скриптами, в которых используются русские символы для кодировки атрибутов, должны быть в кодировке UTF-8. Регистр кода атрибутов должен соответствовать регистру в системе. Размер загружаемого файла со скриптом ограничен 15 Мб. Ссылка на объект: <a href="${api.rest.get(subject, api.auth.getAccessKey('username'))}">Получить объект</a> или <a href="${api.rest.get(subject, 'username')}">Получить объект</a> или <a href="${api.rest.get(subject)}">Получить объект</a> При использовании ссылок в письме следует переключаться в режим html source по ссылке "html" в правом углу редактора, иначе ссылка будет не ссылкой, а html текстом. Ссылка для поиска объекта: <a href="${api.rest.find('ou', [:], api.auth.getAccessKey('username'))}">Получить список отделов</a> или <a href="${api.rest.find('ou', [:], 'username')}">Получить список отделов</a> или <a href="${api.rest.find('ou', [:])}">Получить список отделов</a> Ссылка для редактирования объекта: <a href="${api.rest.edit(subject, ['title' : 'new title'], api.auth.getAccessKey ('username'))}">Переименовать в 'new title'</a> или -7- Глава 2 - REST API <a href="${api.rest.edit(subject, ['title' : 'new title'], 'username')}">Переименовать в 'new title'</a> или <a href="${api.rest.edit(subject, ['title' : 'new title'])}">Переименовать в 'new title'</a> Ссылка для удаления объекта: <a href="${api.rest.delete(subject, api.auth.getAccessKey('username'))}">Удалить</a> или <a href="${api.rest.delete(subject, 'username')}">Удалить</a> или <a href="${api.rest.delete(subject)}">Удалить</a> Ссылка для создания объекта: <a href="${api.rest.create('ou', ['title' : 'новый отдел'], api.auth.getAccessKey ('username'))}">Создать новый отдел</a> или <a href="${api.rest.create('ou', ['title' : 'новый отдел'], 'username')}">Создать новый отдел</a> или <a href="${api.rest.create('ou', ['title' : 'новый отдел'])}">Создать новый отдел</a> Создание объекта (для машинного взаимодействия): <a href="${api.rest.createM2M('ou', ['title' : 'новый отдел'], api.auth.getAccessKey ('username'))}">Создать новый отдел</a> Формат передачи значений атрибутов: Атрибуты типа "Дата/время" передаются в формате "yyyy.MM.dd HH:mm:ss" или "yyyy.MM.dd HH:mm": api.rest.edit(subject, ['dateTimeAttrCode' : '2012.08.25 14:43'], api.auth.getAccessKey ('username')) Атрибуты типа "Дата" передаются в формате "yyyy.MM.dd": api.rest.edit(subject, ['dateTimeAttrCode' : '2012.08.25'], api.auth.getAccessKey ('username')) Для передачи атрибутов-коллекций используется конструкция вида: ['attrCode':['attrValue1','attrValue2']] 2.4 Методы REST API В раздел описываются методы REST API: add-file (добавление файла к объекту), check-status (проверка доступности приложения); create (создание), create-m2m (создание для машинного взаимодействия), delete (удаление), edit (редактирование), exec (выполнение скрипта), get (получение информации об объекте), find (поиск). В методы create, create-m2m, find и edit параметры можно передавать унифицировано разными способами. Способы можно комбинировать: l l через закодированную строку /<action>/<id or fqn>/<attributes> или /<action>/<id or fqn>/ с передачей атрибутов в параметрах request'а; в строке attributes можно передавать строковое представление Json-объекта. -8- Глава 2 - REST API Формат с атрибутами в виде Json-объекта в без кодирования: http://127.0.0.1:8080/sd/services/rest/create/team/{"title":"new", "metaClass":"team$ATTeamCase"}?accessKey=e00c8761-b105-4c2b-a86c-f7fe20cff9b3 Формат без атрибутов, но с параметрами в request'е: http://127.0.0.1:8080/sd/services/rest/create/team?accessKey=e00c8761-b105-4c2b-a86cf7fe20cff9b3&title=new&metaClass=team$ATTeamCase add-file (добавление файла к объекту): Адрес: "/add-file/{uuid}", где: l {uuid} — идентификатор объекта, например, serviceCall$1992, к которому будет приложен файл. Метод вызова: POST. Возвращаемое значение: возвращается только информация о том, создан объект ("Операция выполнена успешно") или нет ("Описание ошибки"). Информации про uuid объекта отсутствует. В параметрах формы, с которой будет выполнено добавление файла, должен быть указан method="POST" и enctype="multipart/form-data". Пример для Linux: curl -F "content=@index.html" http://127.0.0.1:8080/sd/services/rest/addfile/issue$18903?accessKey=bccc11d3-f241-4bed-998e-1e4b3fbf3fe0 check-status (проверка доступности приложения): Адрес: "/check-status" Метод вызова: GET. Пример ссылки: http://192.168.240.92:10080/sd/services/rest/check-status create (создание): Адрес: "/create/{fqn}/{attributes}", где: l l {fqn} — fqn интересующего объекта, например, serviceCall. {attributes} — атрибуты создаваемого объекта. Возвращаемое значение: возвращается только информация о том, создан объект ("Операция выполнена успешно") или нет ("Описание ошибки"). Информации про uuid объекта отсутствует. create-m2m (создание для машинного взаимодействия): Адрес: "/create-m2m/{fqn}/{attributes}", где: l l {fqn} — fqn интересующего объекта, например, serviceCall. {attributes} — атрибуты создаваемого объекта. Возвращаемое значение: созданный объект в формате JSON или причина, по которой объект не был создан. Возможные ответы сервера: l l l Неправильный ключ авторизации: Код возврата 500 Internal Server Error. Переход не может быть выполнен: ключ авторизации [0f3f32de-3a1c-41aa-8510-ad2a025397a8] не найден или не может быть использован повторно. Ключ авторизации не позволяет добавлять/просматривать/искать нужный объект (у пользователя, для которого создали ключ нет прав на объект): Код возврата 401 Unauthorized. Ошибка авторизации.У Вас нет прав на Добавление объекта в классе Заявка. Ключ просрочен: Код возврата 500 Internal Server Error: Переход не может быть выполнен: Время жизни ключа авторизации [f9ec8786-6f29-4c73-abc9-a2548f09247d] истекло. -9- Глава 2 - REST API l l l Параметры для создания объекта закодированы неправильно: Код возврата 500: String length must be a multiple of four. или com.google.gson.stream.MalformedJsonException: Unterminated string at line 1 column 64 или Not a JSON Object: "eyJtZXRhQ2xhc3MiOiJpc3N1ZSRwcm9jdXJlbWVudCIsImRlc2NyaXB0aW9uIjoidGVzdCB0aHJvdWdoIGFwaSJ9" Не указан один из атрибутов, обязательный для создания объекта: Код возврата 500: Запрос '25' не может быть переведен в статус 'Новая'. Произошла ошибка при выполнении скрипта входа. Заявка '25' не может быть изменена по следующим причинам: Не заполнены следующие обязательные атрибуты: Описание. Указаны "лишние" атрибуты для создания объекта. Код возврата 500: Атрибут не найден: issue:olala delete (удаление): Адрес: "/delete/{uuid}", где l {uuid} — uuid удаляемого объекта, например, serviceCall$501. Возвращаемое значение: сообщение об успешности выполненной операции ("Операция выполнена успешно"). edit (редактирование): Адрес: "/edit/{uuid}/{attributes}", где: l l {uuid} — uuid изменяемого объекта, например, serviceCall$501. {attributes} — изменяемые атрибуты. Возвращаемое значение: сообщение об успешности выполненной операции ("Операция выполнена успешно"). exec (выполнение скрипта): Выполнение скриптов доступно только для суперпользователей. Метод вызова POST: l l l Адрес: "/exec". Параметры: o "accessKey" — ключ доступа для суперпользователя. o "script" — файл скрипта для выполнения Возвращаемое значение: результат выполнения скрипта в формате JSON. Пример для Linux: curl -F "script=@./script.groovy" "http://localhost:8888/sd/services/rest/exec?accessKey=0677cc83-2693-4a04-91cbef08e0a7fb7c" Пример для Windows: chcp 65001 curl -F "script=@./script.groovy" "http://sd40.naumen.ru:10080/sd/services/rest/exec?accessKey=deb1c15a-1be3-4837ab4f-c37117a0d9bc" -o result.txt Метод вызова GET: Если скрипт оформить как модуль, и загрузить данный модуль в Naumen Service Desk, то функции, определенные в модуле, можно выполнять через GET запрос. Модули создаются специалистами службы поддержки компании NAUMEN. l Адрес: "/exec" - 10 - Глава 2 - REST API l Параметры: o accessKey — ключ доступа для суперпользователя. o func — название функции в модуле. имя модуля portal123, параметр func=modules.portal123.checkAndCreateEmployee o params — параметры функции, указанной в параметре func. Cтрока целиком, которая подставится в вызов функции func. params="Глушков Михаил Владимирович","13281", "d1c8b6e6d27de546495274caeeece292" Строка с параметрами должна быть корректна закодирована по правилам HTTP. Если в параметрах присутствуют русские буквы, нужно убедиться в правильной настройке сервера приложений и/или nginx/apache/IIS. Полный пример выполнения скрипта через GET: curl http://localhost:8888/sd/services/rest/exec?accessKey=db1ba6f4-c440-437d-b4cee965cf4516d7&func=modules.portal123.checkAndCreateEmployee&params=%22%D0%93%D0%BB%D1%83%D1%88%D0%BA%D0%BE%D0%B2+%D0%9C%D0%B8%D1%85%D0%B0%D0%B8%D0%BB+%D0%92%D0%BB%D0%B0%D0%B4%D0%B8%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B8%D1%87%22%2C%2213281%22%2C%22d1c8b6e6d27de546495274caeeece292%22 При получении данного запроса Naumen Service Desk попытается выполнить следующий код: modules.portal123.checkAndCreateEmployee("Глушков Михаил Владимирович","13281", "d1c8b6e6d27de546495274caeeece292") get (получение информации об объекте): Адрес: "/get/{uuid}", где l {uuid} — uuid интересующего объекта Параметры: l accessKey — ключ доступа для суперпользователя. Метод вызова: GET. Пример ссылки: http://127.0.0.1:8080/sd/services/rest/get/root$101?accessKey=9baec4d6-ad92-4645-b0323e671772804c find (поиск): Адрес: "/find/{fqn}/{attributes}", где: l l {fqn} — fqn типа (класса) объекта. {attributes} — атрибуты и их значения, по которым осуществляется поиск. Параметры: l "accessKey" — ключ доступа для суперпользователя. Метод вызова: GET Примеры ссылок для поиска по различным параметрам: http://127.0.0.1:8080/sd/services/rest/find/team/ {%22metaClass%22:%22ATTeamCase%22}?accessKey=e00c8761-b105-4c2b-a86c-f7fe20cff9b3 http://127.0.0.1:8080/sd/services/rest/find/ou/ {%22title%22:%22Бухгалтерия%22}?accessKey=9e15ba5d-6463-4d24-91c5-bb0892b2166e http://127.0.0.1:8080/sd/services/rest/find/ou/{title:Бухгалтерия}?accessKey=9e15ba5d6463-4d24-91c5-bb0892b2166e - 11 - Глава 2 - REST API http://127.0.0.1:8080/sd/services/rest/find/ou/{title:IT}?accessKey=9e15ba5d-6463-4d2491c5-bb0892b2166e http://127.0.0.1:8080/sd/services/rest/find/ou/%7Btitle:%D0%91%D1%83%D1%85%D0%B3%D0%B0%D0%BB%D1%82%D0%B5%D1%80%D0%B8%D1%8F%7D?accessKey=9e15ba5d-6463-4d24-91c5-bb0892b2166e http://127.0.0.1:8080/sd/services/rest/find/ou/ {%22title%22:%22IT%22}?accessKey=290c008f-a070-4bd6-b3f6-ad3ca567a9c6 http://127.0.0.1:8080/sd/services/rest/find/ou/{'title':'IT'}?accessKey=290c008f-a0704bd6-b3f6-ad3ca567a9c6 http://127.0.0.1:8080/sd/services/rest/find/ou/%7Btitle:%D0%91%D1%83%D1%85%D0%B3%D0%B0%D0%BB%D1%82%D0%B5%D1%80%D0%B8%D1%8F%7D\?accessKey\=9e15ba5d-6463-4d24-91c5-bb0892b2166e - 12 - Глава 3 - Логирование REST Глава 3 - Логирование REST В консоли логируются все REST вызовы в формате: [имя_метода] with args = [параметры вызова метода] INFO logging.RestLogger - REST invocation = [edit] with args = [root$101, 40xeyJ0aXRsZSI6IlR1ZSBKYW4gMjkgMTQ6MTM6MTIgWUVLVCAyMDEzIn0=, 6d54ab64-0b7f-47b7bd53-4ebbe3353add, SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ org.apache.catalina.connector.RequestFacade@38748d00]]] - 13 -