Service rest: Архитектура REST / Хабр
что это такое, примеры запросов, Restful для чайников, интерфейс, разработка, примеры использования сервиса
В этой статье мы разберем оболочку REST API, расскажем, что это такое простыми словами, как работает система.
Так называется способ взаимодействия и обмена данными сервера, своеобразная оболочка, если коротко. Большинство серьезных компаний разрабатывают для внутреннего использования или для своих клиентов этот интерфейс, ведь он способен обеспечить общение между двумя системами и предоставлять информацию. Это небольшая шестеренка, которая приводит в движение другие. Сейчас этот подход сумел вытеснить практически все остальные, включая дизайны, которые были основаны на SOAP.
Что такое REST API
Так называют сокращение английской аббревиатуры, которая переводится как передача состояния представления. Web-службы, которые пользуются этой системой, применяют термин RESTful. Единого стандарта у нее нет — не протокол, а целый архитектурный стиль. Этим она отличается от многих аналогичных. При этом допустимо использовать XML, HTTP, JSON и URL.
Ее разработали еще в 2000 году, но с того момента она очень развилась и сейчас стала одной из самых популярных, отодвинув на задний план аналогичные.
Чтобы объяснить суть restful api для чайников, можно представить калькулятор на любом компьютере. Когда мы нажимаем на кнопки, желая получить расчеты, скрытые функции начинают взаимодействовать. А когда сервис получает результат, он выводит его на экран в виде готовой цифры в графическом интерфейсе.
Здесь архитектура работает аналогичным образом. При нажатии на кнопку выполняются разные операции, чтобы обработать и передать информацию. Они могут не просто получать данные из одной сети, а способны вызывать и обращаться к удаленным серверам, чтобы взять нужное у них.
В качестве примера стоит привести кнопку Facebook, которая умеет задействовать соцсеть, или видео на Youtube, его тоже запускает веб-версия API.
Как работает
В первую очередь стоит разобраться, как действует подход. Преимущества:
- компоненты систем взаимодействуют в гораздо большем масштабе;
- все интерфейсы общие;
- части можно внедрять независимо одну от другой;
- есть промежуточные элементы, которые снижают процент задержки и усиливают безопасность соединения.
Суть оболочки заключается в паре действий, в зависимости от типа запроса. От работы сервера зависит функционал и способности архитектуры. Есть 4 основных вида в отношении информации:
- get — получение, просто передача;
- delete — удаление, в дальнейшем они не отражаются;
- post — регистрация или добавление, регистрация;
- update — обновление, регулярная операция, базы становятся актуальными и свежими.
В качестве пакета обычно отправляется JSON массив на указанный конкретный URL. Там срабатывает так называемая функция, а в зависимости от уже отправленных данных и текущего запроса начинается определенное действие.
Еще одна особенность, о которой стоит упомянуть: не имеет значения, с какого устройства выслана информация, будь это мобильное приложение или браузер компьютера.
Что такое API
Вокруг этого объяснения много споров, потому как он:
- не спецификация — может видоизменяться;
- не протокол — не относится к ним;
- не HTTP — слишком отличается.
Поэтому столько вопросов. Так что же это? Это своеобразная созданная человеком архитектура, которая создается с помощью ограничений и расширений. Если их использовать, то мы получаем стиль, который оптимизировали под пожелания, и подходящий для основных случаев, когда может понадобиться.
В его задачи входит представлять состояние передачи. Уже из названия становится понятно, как должно работать хорошо разработанный софт. Даже сеть страниц можно рассматривать, как машину состояний:
- пользователь видит первое индексное сообщение;
- переходит при помощи ПО, нажимая на ссылку;
- результат он обнаруживает на экране.
Протокол по типу концентрированного REST API, работающий по HTTP равно качественным веб-сервисам
Так можно назвать веб-приложение, которое представляет ресурсы в формате, подходящем для других компьютеров. Они включают в себя разные интерфейсы.
Те варианты, которые применяются для транслирования, тоже можно учитывать как «веб-сервисы». Клиент, который пользуется этим, способен запросить все что угодно, а сервер ему отвечает и предоставляет результаты. Задействуют любой удобный язык программирования или подходящие платформы. Не имеет никакого значения, какой конкретно использовался, так как все выполняется через общий тип.
Это вообще лучшая часть всего созданного в компьютерном мире. Так как они не зависят от языков, то могут совмещаться с самыми разными системами. Когда API документируется, то неважно, чем пользовались разработчики при его создании — Ruby это был, Java или Python или что-то принципиально другое. Все запросы высылаются через один и тот же HTTP, решения приходят таким же способом.
Хотите внедрить «Склад 15»?
Получите всю необходимую информацию у специалиста.
Спасибо!
Спасибо, ваша заявка принята!
Продолжить
Дело в том, что этот протокол используется именно для реализации передачи, это своеобразный шаблон. Сервер способен говорить на любом языке программирования, анализирует он по-своему, при этом сам не находится в зависимости от них, поэтому приходящая и уходящая информация схожа.
SOAP стоит отнести к предкам интерфейсов по типу REST API
Еще перед тем, как прикладное программирование нового поколения стало популярным и везде используемым, у него был аналог — SOAP. Он был максимально распространен. А чтобы понять разницу, стоит разобраться в истоках.
SOAP это протокол, который работает по заранее определенному стандарту. Ему для работы требуется XML, это определит формат, в котором будут отражаться входящие и исходящие запросы. Так как это стандартная вещь, подвид можно определить, если использовать файл WSDL — он помогает расшифровывать язык, на котором пишут веб-службы. Он определяет, есть ли атрибуты или какие-то расширенные элементы в передающихся сообщениях. Это машиночитаемая часть функционирования сети, поэтому пользуются им только сервера, которые действуют и общаются, чтобы облегчить связь.
Все сообщения внутри SOAP собираются в своеобразные «конвертики», в которых есть заголовок и основное тело. Все это «пакуется» при помощи заранее сформированной схемы по принципу XML.
Основная проблема этой системы в том, что формат, который используется для передачи, излишне тяжелый. Это вызывает серьезные проблемы в выполняемых сценариях на мобильных устройствах, задерживает загрузку, делает слишком медленной обработку. Там, где пропускная способность очень важна, эту схему не хочется использовать. Это одна из причин, которые стали поводом для разработки и создания rest сервиса.
Самый короткий обзор HTTP
Начать это изучение стоит с открытия любого браузера и веб-страницы. Можно ввести запрос и внизу появятся результаты. Нужно щелкнуть по любому из вариантов, ПО переведет на страницу. Если есть ссылки, то можно кликнуть по ним, это отправит пользователя на следующую веб-страничку.
Именно так обычно выглядит просматривание ресурсов. Но в этот момент происходит очень много вещей, не видимых глазу клиента. В эти минуты между браузером и хабом происходит много всего. Создается и отправляется требование к посещаемому сайту, оттуда приходит ответ.
Как протоколируется HTTP
Когда вводится определенный адрес, то на относящийся к нему медиасервер высылается сгенерированный вопрос. Там формируется результат и через доли секунды высылается. Важно учесть, в каком виде будут создаваться и переправляться эти пакеты. Обычно они определяются одним этим протоколом.
Когда набирается в браузере URL, то он высылает запрос GET на тот веб-сайт, который относится к введенному. Система отвечает также, с содержанием HTML, который читает код и отражает на экране.
Например, заполняется форма на веб-странице, где есть целый перечень элементов, в который необходимо вписывать данные. Когда все поля заняты, клиент нажимает на кнопку «Отправить», требование отправляется на хаб.
Веб-сервисы порядка HTTP и RESTful
С помощью Hyper Text Transfer Protocol можно обеспечить минимальный уровень для создания разнообразных по функционалу медиасервисов. Поэтому необходимо понимать, как это работает.
Все основывается на абстракциях:
- Ресурс. Ключевое концентрирующее понятие. Это все, что пользователь желает показать сквозь себя.
- URI. Для каждого хаба разрабатываются свои системы. Чтобы идентифицировать какую-то из них для отображения, ему следует присвоить универсальный идентификатор.
- Компоненты. У каждого есть собственная структура, которой необходимо придерживаться. Обычно это строка, которая может определить тип сообщения, заголовки и само тело.
А теперь давайте остановимся на этом подробнее.
Ресурс приложения
Абстракция, на которой концентрируется рабочий протокол HTTP. Так разработчик составляет то, что хочет транслировать миру через создаваемое. К примеру, если готовится модель, в которой можно управлять задачами, ресурсная составляющая складывается из определенных пользователей, их целей и списка того, что должно выполниться.
Объяснение URI
Вне зависимости от цели софта, это последовательность, определяющая конкретный физическое или абстрактное ПО. Кроме того, рекомендуется определить и отделить ее от аналогичных полей, которые планируется представлять публике. Необходимо выбрать конкретный способ. А потом каждому сайту прикрепляется URI — это уникальный идентификатор. О том, какие команды для этого выполняются, мы уже говорили выше.
REST с точки зрения ресурсов
Если используется этот вид представления, нужно думать о приложении с позиции ресурсной составляющей. Следует определить, какие из них хотелось бы показать внешнему миру и другим пользователям. Когда будут выбраны части, подгоняемые под протокол, предстоит использовать глаголы для осуществления операций, где будут задействованы эти процедуры.
Служба реализуется таким образом:
- В каком варианте осуществляется обмен. В нем определены ограничения. Из популярных можно выделить JSON, но никто не запрещает задействовать и другие, например, XML.
- Чем обеспечена трансляция. Все пакеты транспортируются на HTTP, REST всегда построен на нем.
- Как определяется сервис. В этой позиции нет единого стандарта, архитектура гибкая и подстраиваемая. В отдельных сценариях это оказывается довольно серьезным недостатком. Дело в том, что может потребоваться возможность разбираться в форматах, в которых отправляются запросы и ответы. Но чаще всего это удобный механизм, где широко задействованы языки программирования веб-приложений и сайтов.
Структура компонентов HTTP
Веб-сайты, построенные на rest api example, строятся по конкретной структурной схеме. Что у него есть:
- строка — в нем определяется тип, которым транслируется сообщение;
- заголовок — характеризует, как выглядит тело будущего текста, с какими параметрами планируется передавать пакет данных и другие важные сведения;
- само сообщение — это необязательное поле, его допускается пропускать.
Методы текущих запросов
То, что используется в вопросе на сервер, показывает на то, что пользователь хочет сделать. Есть 4 маркера:
- GET — для чтения более подробной информации о том, о чем спрашивается. После получения данных GET возвращается и предоставляет ресурс в виде XML или JSON. Если выявляется ошибка, то выскакивает ошибка 404 (не найдено) или 400 (плохой регистр).
- POST — используется, если нужно сформировать свежий или вложенный сайт, страницу. При организации нового требование движется к родительскому контенту и берет на себя ответственность организовать связь.
- PUT — обновить то, что уже существует. Тело должно иметь обновленные данные с оригинального сайта — как полностью, так и только часть. Чтобы создать новые экземпляры, лучше задействовать предыдущий вариант.
- DELETE — стереть имеющийся объект, который имеет конкретный URI. Если все выполнено успешно, то возвращается код 200 вместе с реакцией, содержащей удаленный пункт. Еще один возможный вариант — 204, если нет тела. Когда выполняется этот запрос, то ресурс удаляется.
Код, который коротко поясняет ответ сервера
Есть 2 типичных результата, которые выводятся на странице:
- 200 — успешно найдена;
- 404 — отсутствует на сайте.
Если вашему бизнесу необходимо ПО, которое поможет оптимизировать текущую деятельность, наладить автоматизацию рутинных операций, обращайтесь в «Клеверенс». Мы разрабатываем и реализуем мобильные системы учета, предоставляя широкий спектр решений для магазинов, складов, различных учреждений и производства. В качестве Application Programming Interface в наших продуктах используется REST API.
JSON: что это такое
В каждом руководстве указывается, что так называется формат, в котором хранится информация, которую может прочитать человек. В файле содержится только текст, а расширение проставляется такое же, как заголовок пункта.
Он хранит структурированные данные и передает их от сервера до клиента и обратно. Эти пакеты являются более легкой альтернативой другому расширению с похожим функционалом — XML.
Его задействуют, чтобы добиться асинхронной загрузки данных. Это нужно, чтобы сайты могли обновлять свои медиафайлы без перезагрузки страницы.
Сейчас это очень популярный формат, потому что он занимает меньше места, а продуктивность с ним вырастает в несколько раз.
С его помощью пользователи запрашивают информацию из других доменов с применением тегов типа script. Никакие иные включить не получится, так как существуют правила ограничения домена.
REST API с примерами использования и запросов
Всемирная паутина основана на этой архитектуре. Поэтому, если составлять стиль без них, то софт получится неоптимальным. Как следствие, не всегда можно открыть ресурс и воспользоваться им.
Где может быть задействована:
- есть ограничение на пропускную способность, нужно повысить возможности загрузки страниц или приложений;
- появилась необходимость кешировать;
- предполагается, что систему планируется значительно масштабировать;
- в сервисах, которые используют в своей работе AJAX.
Главное — не путать написание. Rest IP — это не существующее название.
Слово API применяется в различных значениях. Вот пара примеров его использования:
- в качестве небольшого фрагмента с определенной функцией;
- сервер, полностью или завершенная часть.
Например, требуется создать веб-сервер, в котором будет располагаться медиаконтент о каком-то производстве, о его доходе, персонале и т.д.. Всем частям присваивается свой id.
Хотите внедрить «Магазин 15»?
Получите всю необходимую информацию у специалиста.
Спасибо!
Спасибо, ваша заявка принята.
Продолжить
Основные запросы
Как мы уже говорили выше, есть 4 основных вида:
- Delete. Стирает имеющиеся объекты.
- Put. Обновляет существующее поле.
- Get. Читает или получает информацию.
- Post. Помогает формировать новый ресурс.
Вывод
Мы рассмотрели, как выполняется разработка rest api service и ее методы, как он действует в рамках различных протоколов и как быстро отвечает пользователю. Постарались подробно остановиться на вопросах целесообразности его создания и том, из каких компонентов он состоит. Изучили методы HTTP, что такое JSON и привели примеры применения. Сервис выгодно выделяется на фоне других систем, поэтому его стоит задействовать там, где скорость отклика играет решающую роль.
Количество показов: 6716
Лучшие практики проектирования REST API
December 13, 2016 Jazz Team Технические статьи,
Введение
Здравствуйте, дорогие читатели! Прежде чем вы начнёте читать эту статью, я хотел бы описать цели её создания и рассказать, что побудило меня на её написание.
На одном из проектов нашей компании появилось необходимость спроектировать серверное приложение в стиле REST. Изначально нам казалось, что это довольно простая задача и для её решения нам хватит только собственного опыта.
Но, когда стартовал процесс разработки архитектуры и приведения REST-сервисов к единому стилю, у нас с коллегами начали возникать спорные вопросы и появляться разные точки зрения на реализацию того или иного аспекта. Тут мы поняли, что необходимо открыть гугл и обратиться к помощи коллективного разума, изучить предлагаемые лучшие практики, которые необходимо использовать при проектировании RESTful приложения.
Данная статья будет полезна для тех людей, которые уже имеют некоторый опыт работы с веб-приложениями (и возможно с REST-сервисами), но нуждаются в закреплении и стандартизации полученных знаний.
Определение
Для начала нужно определиться, что же такое REST. Википедия даёт на этот вопрос следующий ответ. REST (Representational State Transfer — «передача состояния представления») — архитектурный стиль взаимодействия компонентов распределённого приложения в сети. REST представляет собой согласованный набор ограничений, учитываемых при проектировании распределённой гипермедиа-системы.
Своими словами я бы объяснил понятие REST как “набор рекомендаций, который позволяет унифицировать взаимодействие клиентских и серверных приложений”.
В данной статье я постараюсь рассказать об этих самых “рекомендациях”, которые помогут проектировать и создавать REST-сервисы согласно общепринятым практикам.
Также нужно понимать, что такое REST-сервис. Я бы дал определение REST-сервису, как “точка взаимодействия клиентского приложения с сервером”. Говоря Java терминологией – это сервлет, на который клиент посылает запрос.
Проблематика
Но прежде чем начинать описывать правила, я хотел бы донести мысль о том, что REST – это не стандарт, потому нет единых строгих правил, которых стоит придерживаться. Это значит, что до сих пор нет полной согласованности о том, какие решения лучше применять в той или иной ситуации. Очень часто заходят споры о том, какие HTTP методы использовать и какой HTTP код возвращать в каждой конкретной ситуации.
Более подробно о проблемах REST можно почитать тут.
Соответственно, рекомендации, которые я опишу ниже, стоит принимать во внимание, но не следовать им на 100%, если это может повредить какому-либо другому аспекту проекта.
Однако если вы будете следовать всем рекомендациям, то получится спроектировать очень понятную и поддерживаемую систему, с которой приятно работать.
Название сервиса
Для начала необходимо выбрать имя для REST сервиса. Под именем сервиса я подразумеваю его путь в URI запросе. Например, http://my-site.by/api/rest/service/name. Для выбора имени нам нужно понимать что такое “ресурсы” в архитектуре REST.
Представление ресурса
В терминологии REST что угодно может быть ресурсом — HTML-документ, изображение, информация о конкретном пользователе и т.д. Если ресурс представляет собой некоторый объект, его легко представить, используя некоторый стандартный формат, например, XML или JSON. Далее сервер может отправить данный ресурс, используя выбранный формат, а клиент сможет работать с полученным от сервера ресурсом, используя этот же формат.
Пример представления ресурса “профиль” в формате JSON:
{
"id":1,
"name":"Mahesh",
"login":"manesh"
}
REST не накладывает явных ограничений на формат, который должен быть использован для представления ресурсов, но есть ряд правил, которым нужно следовать при разработке формата, который будет использоваться для представления ресурса:
- Клиент и сервер должны “понимать” и иметь возможность работать с выбранным форматом.
- Ресурс можно полностью описать, используя выбранный формат независимо от сложности ресурса.
- Формат должен предусматривать возможность представления связей между ресурсами.
Пример представления ресурса “заказ” и его связи с ресурсом “профиль”:
{
id: 11254,
currency: "EUR",
amount: 100,
profile: {
id: 11,
uri: "http://MyService/Profiles/11"
}
}
Как видно, не обязательно полностью дублировать всю структуру ресурса, на который ссылается другой ресурс. Вместо этого можно использовать понятную ссылку на другой ресурс.
Обращение к ресурсу
Каждый ресурс должен быть уникально обозначен постоянным идентификатором. «Постоянный» означает, что идентификатор не изменится за время обмена данными, и даже когда изменится состояние ресурса. Если ресурсу присваивается другой идентификатор, сервер должен сообщить клиенту, что запрос был неудачным и дать ссылку на новый адрес. Каждый ресурс однозначно определяется URL. Это значит, что URL по сути является первичным ключом для единицы данных. То есть, например, вторая книга с книжной полки будет иметь вид /books/2, а 41 страница в этой книге — /books/2/pages/41. Отсюда и получается строго заданный формат. Причем совершенно не имеет значения, в каком формате находятся данные по адресу /books/2/pages/41 – это может быть и HTML, и отсканированная копия в виде jpeg-файла, и документ Word.
Рекомендуется при определении имени REST-сервиса использовать имена ресурсов во множественном числе. Такой подход позволяет добавлять новые REST-сервисы лишь расширяя имена уже существующих. Например, сервис /books вернёт нам список всех книг, /books/3 вернёт информацию о 3-ей книге, а сервис /books/3/pages вернёт все страницы 3-ей книги.
Для сервисов, которые выполняют какие-то специфические действия над ресурсом, есть 2 подхода для указания действия: в имени сервиса или в его параметрах. Например, /books/3/clean или /books/3?clean. Я предпочитаю первый вариант, так как обычно такие сервисы не редко используют POST методы, которые не поддерживают передачу параметров в URl, что делает сервис, на мой взгляд, не очень читабельным. Используя определение типа действия в имени сервиса, мы делаем наш сервис более расширяемым, так как он не зависит от типа HTTP метода.
Также очень не рекомендуется использовать имена, включающие в себя несколько слов и описывающие бизнес составляющую сервиса (как это рекомендуется делать при именовании java методов). Например, вместо /getAllCars лучше сделать метод /cars. Если же метод нельзя никак описать одним словом, то необходимо применять единый стиль разделителей, я обычно использую ‘-’, что является наиболее популярным подходом. Например, /cars/3/can-sold.
Более подробно о проектировании названий REST-сервисов можно прочитать в этой статье.
HTTP методы
Далее нам необходимо выбрать HTTP метод, который будет использовать наш REST-сервис, ведь имея даже одинаковое имя, но разные методы, REST-сервисы выполняют совершенно различные действия.
В REST используются 4 основных HTTP метода: GET, POST, PUT, DELETE. В большинстве случаев каждый из методов служит для выполнения предопределённого ему действия из CRUD (create, read, update, delete — «создание, чтение, обновление, удаление»).
POST – create, GET – read, PUT – update, DELETE – delete.
ВАЖНОЕ ДОПОЛНЕНИЕ: Существуют так называемые REST-Patterns, которые различаются связыванием HTTP-методов с тем, что они делают. В частности, разные паттерны по-разному рассматривают POST и PUT. Однако, PUT предназначен для создания, замены или обновления, для POST это не определено (The POST operation is very generic and no specific meaning can be attached to it). Поэтому иногда POST и PUT можно поменять местами. Но в большинстве случаев POST используют для создания, а PUT для редактирования, и чуть позже я объясню почему.
Приведу несколько примеров использования различных методов для взаимодействия с ресурсами.
- GET /books/ – получает список всех книг. Как правило, это упрощенный список, т.е. содержащий только поля идентификатора и названия объекта, без остальных данных.
- GET /books/{id} – получает полную информацию о книге.
- POST /books/ – создает новую книгу. Данные передаются в теле запроса.
PUT /books/{id} – изменяет данные о книге с идентификатором {id}, возможно заменяет их. Данные также передаются в теле запроса. - OPTIONS /books – получает список поддерживаемых операций для указанного ресурса (практически не используется)
- DELETE /books/{id}– удаляет данные с идентификатором {id}.
Безопасность и идемпотентность
Очень помогут в выборе HTTP метода знания о безопасности и идемпотентности этих методов.
Безопасный запрос — это запрос, который не меняет состояние приложения.
Идемпотентный запрос — это запрос, эффект которого от многократного выполнения равен эффекту от однократного выполнения.
Судя по данной таблице, GET-запрос не должен менять состояние ресурса, к которому применяется. PUT и DELETE запросы могут менять состояние ресурса, но их можно спокойно повторять, если нет уверенности, что предыдущий запрос выполнился. В принципе, это логично: если многократно повторять запрос удаления или замены определенного ресурса, то результатом будет удаление или замена ресурса. Но POST запрос, как мы видим из таблицы, небезопасный и неидемпотентный. То есть мало того, что он меняет состояние ресурса, так и многократное его повторение будет производить эффект, зависимый от количества повторений. Ему по смыслу соответствует операция добавления новых элементов в БД: выполнили запрос Х раз, и в БД добавилось Х элементов.
Также приведу пример того, почему GET-запросы не должны изменять состояние ресурса. GET-запросы могут кэшироваться, например, на уровне прокси-сервера. В таком случае запрос может даже не дойти до сервера приложения, а в качестве ответа прокси-сервер вернёт информацию из кэша.
HTTP коды
В стандарте HTTP описано более 70 статус кодов. Хорошим тоном является использование хотя бы основных.
- 200 – OK – успешный запрос. Если клиентом были запрошены какие-либо данные, то они находятся в заголовке и/или теле сообщения.
- 201 – OK – в результате успешного выполнения запроса был создан новый ресурс.
- 204 – OK – ресурс успешно удалён.
- 304 – Not Modified – клиент может использовать данные из кэша.
- 400 – Bad Request – запрос невалидный или не может быть обработан.
- 401 – Unauthorized – запрос требует аутентификации пользователя.
- 403 – Forbidden – сервер понял запрос, но отказывается его обработать или доступ запрещен.
- 404 – Not found – ресурс не найден.
- 500 – Internal Server Error – разработчики API должны стараться избежать таких ошибок.
Эти ошибки должны быть отловлены в глобальном catch-блоке, залогированы, но они не должны быть возвращены в ответе.
Чем обширнее набор кодов, который мы будем использовать, тем более понятный будет API, который мы создаём. Однако нужно учесть, что некоторые коды браузеры обрабатывают по-разному. Например, некоторые браузеры получив код ответа 307 сразу же выполняют редирект, а некоторые позволяют обработать такую ситуацию и отменить действие. Прежде чем использовать тот или иной код, необходимо полностью понимать, как он будет обрабатываться на клиентской стороне!
Более подробно о HTTP кодах можно почитать тут.
Headers
Рекомендуется при проектировании REST-сервисов явно указывать заголовки, в которых обозначен формат обмена данными:
- Content-Type – формат запроса;
- Accept – список форматов ответа.
Параметры поиска ресурсов
Чтобы упростить использование сервисов, отвечающих за возвращение какой-либо информации, и вдобавок сделать их наиболее производительными, необходимо использовать в качестве параметров запроса параметры для сортировки, фильтрации, выбора полей и пагинации.
Фильтрация
Используйте уникальный параметр запроса для каждого поля, чтобы реализовать фильтрацию. Это позволит ограничить количество выводимой информации, что оптимизирует время обработки запроса.
Например, чтобы вывести все красные книги необходимо выполнить запрос:
GET /books?color=red
Сортировка
Сортировка реализуется подобно фильтрации. Например, чтобы вывести все книги, отсортированные по году публикации по убыванию и по названию по возрастанию нужно выполнить следующий запрос:
GET /books?sort=-year,+name
Пагинация
Для того, чтобы поддержать возможность загрузки списка ресурсов, которые должны отображаться на определённой странице приложения, в REST API должен быть предусмотрен функционал пагинации. Реализуется он с помощью знакомых нам по SQL параметрам limit и offset. Например:
GET /books?offset=10&limit=5
Помимо того хорошим тоном является вывод ссылок на предыдущую, следующую, первую и последнюю страницы в хидере Link. Например:
Link: <http://localhost/api/books?offset=15&limit=5>; rel=”next”,
<http://localhost/api/books?offset=50&limit=3>; rel=”last”,
<http://localhost/api/books?offset=0&limit=5>; rel=”first”,
<http://localhost/api/books?offset=5&limit=5>; rel=”prev”
Рекомендуется также возвращать общее количество ресурсов в хидере X-Total-Count.
Выбор полей ресурса
Для более удобного использования сервиса, для экономии трафика можно предоставить возможность управлять форматом вывода данных. Реализуется предоставлением возможности выбора полей ресурса, которые должен вернуть REST сервис. Например, если необходимо получить только id книг и их цвета, необходимо выполнить следующий запрос:
GET /books?fields=id,color
Хранение состояния
Одно из ограничений RESTful сервисов заключается в том, что они не должны хранить состояние клиента, от которого получают запросы.
Пример сервиса, не хранящего состояние:
Request1: GET http://MyService/Persons/1 HTTP/1.1
Request2: GET http://MyService/Persons/2 HTTP/1.1
Каждый из этих запросов может быть обработан независимо от другого.
Пример сервиса, хранящего состояние:
Request1: GET http://MyService/Persons/1 HTTP/1.1
Request2: GET http://MyService/NextPerson HTTP/1.1
Чтобы обработать второй запрос, серверу потребуется “запомнить” id последнего человека, который был запрошен клиентом. Т.е. сервер должен “запомнить” свое текущее состояние, иначе второй запрос не может быть обработан. При проектировании сервиса, следует избегать необходимости в хранении состояния, так как это имеет ряд преимуществ.
Преимущества сервиса, не хранящего состояние:
- сервис обрабатывает запросы независимо друг от друга;
- архитектура сервиса упрощается;
- не требуется дополнительных усилий для реализации сервисов с использованием протокола HTTP, который также не хранит состояния.
Недостатки сервиса, не хранящего состояние:
- клиент сам должен отвечать за передачу необходимого контекста сервису.
Версионность
Хорошим тоном является поддержка версионности REST API. Это позволит в дальнейшем легко расширять API, без обязательного внесения изменений в клиенты, которые уже пользуются им.
Имеются несколько подходов реализации версионности:
- С использованием Accept хидера. В данном случае версия API указывается в Accept – Accept:text/v2+json
- С использованием URI. В таком подходе версия API указывается прямо в URI – http://localhost/api/v2/books
- Использование кастомного хидера. Можно использовать собственный хидер, который будет отвечать только за передачу версии API – API-Version:v2
- Использование параметра запроса. Можно использовать параметр запроса для передачи версии API – /books?v=2
Каждый из представленных способов имеет право на существование, у каждого есть свои плюсы и минусы. Однако только Вам решать, какой способ реализации версионности подойдёт Вашему проекту.
Документация
Для удобного пользования нашими REST сервисами нужно создать хорошую и понятную документацию. Для этих целей можно использовать различные инструменты, например, Mashape или Apiary, но я рекомендую использовать Swagger.
Swagger – это технология, которая позволяет документировать REST-сервисы. Swagger поддерживает множество языков программирования и фреймворков. Плюс, Swagger предоставляет UI для просмотра документации.
Получить более подробную информацию о Swagger можно по данной ссылке.
Архивирование
Для экономии трафика рекомендуется использовать архивирование, при передаче больших данных. Это сократит время выполнения запроса. В большинстве современных фреймворков данная функция реализована по умолчанию.
Кэширование
Также для сокращения запросов к БД и увеличения быстродействия наших REST сервисов рекомендуется применить механизм кэширования. Кэширование можно настраивать как на уровне сервера, так и в самом приложении, в зависимости от ситуации.
Кэшированием можно управлять используя следующие HTTP заголовки:
- Date – дата и время создания ресурса.
- Last Modified – дата и время последнего изменения ресурса на сервере.
- Cache-Control – заголовок HTTP 1.1 используемый для управления кэшированием.
- Age – время, прошедшее с момента последнего получения ресурса, заголовок может быть добавлен промежуточным (между клиентом и сервером) компонентом (например, прокси сервер)
Рекомендации по кэшированию:
- Рекомендуется кэшировать статические ресурсы, такие как изображения, стили css, файлы javascript.
- Не рекомендуется указывать большое время жизни кэша.
- Динамическое содержимое должно кэшироваться на короткое время или не кэшироваться вообще.
Общие рекомендации
Тип представления ресурса
Хотя REST не накладывает явных ограничений на формат, который должен быть использован для представления ресурсов, наиболее популярными являются XML и JSON.
Существует множество библиотек в разных языках программирования для удобной работы с этими форматами. Несмотря на это, рекомендуется использовать именно JSON для представления ресурсов. Это более легкий, читабельный формат, с которым проще работать по сравнению с XML, а так же проще выполнять сериализацию/десериализацию объектов в различных языках программирования.
Однако иногда для поддержки некоторых REST клиентов сервису необходимо поддерживать XML формат. В таком случае можно реализовать поддержку обоих форматов и указывать в параметре запроса, в каком формате должен быть представлен ответ.
Использование проверенных решений для авторизации
Используйте для авторизации проверенные и отработанные схемы.
Не изобретайте свой велосипед с использованием md5 подписей данных и прочего, доверьтесь профессионалам в области защиты данных. Всё уже придумано за Вас: OAuth, OpenID, APIKeys.
Обработка исключений
При возникновении ошибочных ситуаций необходимо выводить отформатированную и понятную информацию. Это относится в первую очередь к статус коду в HTTP ответе. Ошибки в сервисах чаще всего относятся к двум типам:
- 4xx – ошибки клиента;
- 5xx – ошибки сервера.
В случае ошибки клиента, например, ошибки валидации какого-то из параметров запроса, в теле ответа рекомендуется передавать полезную информацию об ошибке: сообщение, описание, код (например в формате JSON). В случае ошибки сервера отправлять дополнительную информацию в теле ответа не всегда возможно, например, в случаях когда сервер не доступен.
Плохим тоном является вывод всего стэк трейса исключения. Рекомендуется для каждой исключительной ситуации иметь свой код. В дальнейшем при выводе информации об ошибке можно будет добавить ссылку на документацию, в которой данный код будет выступать уникальным идентификатором.
Например:
{
"code" : 1234,
"message" : "Something bad happened :(",
"description" : "More details about the error here",
“moreInfo”: “http:/localhost/api/v2/errors/1234”
}
Полезные ссылки
HTTP метод, REST, RESTful, мануал, техническая статья
Что такое REST API?
Что такое REST? Если вы занимаетесь, веб-программированием, наверняка, вам приходилось сталкиваться с этим понятием.
Давайте будем разбираться, что это такое и зачем это нужно.
Представим, что мы являемся веб-программистами и разрабатываем какое-то большое веб-приложение. Может быть мы разрабатываем свою социальную сеть, например, как вконтакте, или сервис email рассылок, и.т.д.
На начальном этапе всем может быть хорошо, но как только дело дойдет до того, что нужно будет дать возможность каким-то другим сервисам или приложениям взаимодействовать с нашим, здесь могут начинаться проблемы.
Например, нужно дать возможность изменять настройки нашего веб-приложения, например, через мобильное приложение или мы хотим выводить какие-то внутренние части нашего приложения на сторонних сайтах.
Например, если мы разрабатываем социальную сеть вроде вконтакте, нам может понадобиться выводить количество подписчиков в определенной группе на определенном сайте.
Как мы можем приложению с другого сайта запросить данные с нашего веб-сервера и, чтобы он мог вывести эту информацию.
Какое-то другое приложение может запрашивать какую-то другую информацию.
Также наше приложение может общаться с внешней базой данных. Сохранять и получать оттуда какие-то данные.
Для того, чтобы это стало возможным, нашему сервису нужен некий интерфейс, возможность, которая могла бы предоставить всем сторонним приложениям возможность получать данные с нашего приложения обновлять и обмениваться данными.
Системы, которым предстоит взаимодействовать в этой клиент-серверной системе данных, могут быть очень разные. На каждом клиенте может использоваться свой язык программирования, операционная система и.т.д.
Обмениваться данными всем этим системам может быть довольно сложно.
Как же сделать, чтобы все эти системы умели понимать друг друга даже если они разговаривают на разных языках.
Если все эти системы умеют работать по протоколу HTTP по сети Интернет, помочь решить проблему стыковки этих разных систем может так называемый REST.
Что это это такое.
REST (Representational State Transfer («передача состояния представления»)).
По сути, REST — это просто набор правил. Там есть 6 основных правил, как программисту организовать написание серверного кода приложения, чтобы все системы легко обменивались данными и все системы можно было бы легко масштабировать и увеличивать.
REST — это просто набор правил к написанию кода. Код приложения этим правилам может как соответствовать (так называемый RESTful сервис), так и не соответствовать.
Можно обмениваться данными с разными сервисами и без REST. В этом случае у вас могут возникать сложности в обмене данными между этими устройствами.
REST — это некий стандарт, который приводит все в соответствие и устройства могут без проблем этими данными обмениваться.
Если вы разработали RESTfull приложение, то по окончании разработки у вас будет некий список url-адресов, с помощью которых можно будет общаться с нашим веб-сервером. Сервер с их помощью может получать запросы на получение, обновление, добавление или удаление данных.
С помощью списка таких адресов мы предоставляем некий интерфейс, с помощью которого другие сервисы с ним могут взаимодействовать.
Обращаясь к списку таких адресов можно выполнять такие запросы как GET (получить), POST (сохранить), PUT (обновить), DELETE (удалить).
Различные примеры приложений, которые разработаны по принципам REST, вы можете посмотреть в видео выше.
REST-сервис · Loginom Help
Задаются параметры подключения, запроса и ответа REST-сервиса. Выходные данные подключения используются узлом REST-запрос.
Параметры подключения
- URL сервиса — задается адрес отправки запросов к REST-сервису.
Метод — выбирается один из HTTP-методов, используемых при отправке запросов к сервису: GET, DELETE, POST, PUT, PATCH.
- При выборе методов GET, DELETE доступны настройки:
- Допустимый Content-type ответа — узел REST-запрос, использующий данное подключение, проверяет тип ответа на соответствие заявленному в данном параметре. При несоответствии типов выходной набор этого узла будет содержать сообщение об ошибке. Данная проверка не осуществляется, если параметр имеет значение
*/*
. - Параметры запроса — задается перечень параметров запроса, их имена и типы данных. В последующем, в узле вызова REST-сервиса значения параметров подставляются в URL запроса.
- Допустимый Content-type ответа — узел REST-запрос, использующий данное подключение, проверяет тип ответа на соответствие заявленному в данном параметре. При несоответствии типов выходной набор этого узла будет содержать сообщение об ошибке. Данная проверка не осуществляется, если параметр имеет значение
- При выборе методов POST, PUT, PATCH доступны настройки:
- Тип Content-type запроса — задается значение заголовка
Content-type
HTTP-запроса к REST-сервису. Доступен как выбор из списка предопределенных значений, так и ввод произвольного значения. - Допустимый Content-type ответа — то же, что и для GET, DELETE методов (см. выше).
- Тип Content-type запроса — задается значение заголовка
- При выборе методов GET, DELETE доступны настройки:
- Таймаут подключения (мсек) — максимальное время установки TCP-соединения с сервером в миллисекундах, по истечении которого соединение будет прервано со статусом ошибки. Если параметр равен нулю, то таймаут не ограничен.
- Таймаут обмена данными (мсек) — максимальное время, которое будет затрачено на отправку HTTP-запроса и получение ответа, по истечении которого обмен будет прерван со статусом ошибки. Если параметр равен нулю, то таймаут не ограничен.
- Игнорировать ошибки SSL сертификата — если данный флаг установлен, то ошибки при проверке сертификата сервера, к которому производится подключение, игнорируются.
Авторизация при выполнении запроса
- Тип авторизации — представляет выпадающий список с вариантами авторизации:
- Не требуется — при выборе этого пункта Loginom не проводит авторизацию при подключении к сервису.
- Имя пользователя и пароль — выбирается, если требуется авторизация по имени/паролю. Поддерживаются следующие типы авторизации по имени пользователя и паролю:
- Basic;
- Digest;
- NTLM;
- Passport;
- Negotiate.
- Токен OAuth — выбирается при подключении к веб-сервису посредством протокола OAuth версии 2.0.
- Предоставить сертификат клиента — выбирается для авторизации по SSL посредством сертификата.
- Имя пользователя, Пароль — поле становится активным, если выбран тип Имя пользователя и пароль. Задают параметры авторизации пользователя при его регистрации в системе веб-сервиса.
- Токен OAuth — поле становится активным, если выбран тип Токен OAuth. Вводится строка токена.
- Хранилище сертификатов — выпадающий список, который становится доступен при выборе Предоставить сертификат клиента. Из списка выбирается одно из хранилищ сертификатов, имеющихся в системе. Затем в таблице под списком выбирается используемый для авторизации сертификат.
REST и SOAP. Почувствуйте разницу
Некоторое время назад я гуглил по поводу “REST vs SOAP”, прочитал пару статей и вроде бы все понял, но не почувствовал от этого никакого удовлетворения. Что-то было не так, то ли я не почувствовал основную идею, то ли просто читал, одновременно слушая конференцию Зава и думая о новой фиче в проекте. Поэтому, когда увидел в рассылке вопрос о том, кто мог бы организовать что-то образовательное по теме REST, я сразу же увидел в этом личную выгоду разобраться в теме поглубже. Пройдя кастинг, приступил к задаче. Пару месяцев назад при беглом изучении вопроса я понял о REST примерно следующее:
- Все является ресурсами с уникальным идентификатором (URL).
- Все операции клиента с сервером stateless, т. е. сервер не должен хранить вообще никакой информации о клиенте – никакой сессии.
- Все запросы можно поделить на 4 типа в соответствии с CRUD, причем каждому типу сопоставляется HTTP метод – Post, Get, Put и Delete.
- Вся логика крутится вокруг ресурсов, а не операций.
Денис Афанасьев
Аббревиатура REST – дурацкая, запутывающая и по сути ничего не объясняющая. Айтишники вообще породили массу дурацких названий, можно вспомнить ActiveX или ASP…
Вот с такими воспоминаниями я начал бороздить просторы Интернета. Первой мыслью было: а почему выбрано название REST? Representational State Transfer, в переводе википедии «передача состояния представления»… Никакая картинка в голове не вырисовывается даже при четвертом вчитывании. Здесь пытаются ответить на мой вопрос и даже ссылаются на то, как Рой Филдинг (человек, сформулировавший принципы REST) сам объяснял происхождение названия.
Мысль сводится к тому, что запрос ресурса с сервера переводит клиентское приложение в определенное состояние (state), а запрос следующего ресурса меняет состояние приложения (transfer). А “Representational” означает то, что ресурс возвращается не просто так, а в каком-то представлении, например в представлении для машины или в представлении для человека. Сложно, как по мне, и сбивает с толку, т.к. состояние – это как раз то, что отсутвует в отношениях клиент-сервер в архитектуре REST.
Я бы назвал как-то вроде «Стандартизированное оперирование данными», вот только сначала надо что-то придумать, а потом уже яркое название выбирать. А Филдинг в своей диссертации признается, что название придумано не для того, чтобы было понятно, о чем речь а «is intended to evoke an image of how a well-designed Web application behaves».
Но это ничего, не будем обижаться на уважаемого человека, мы тоже в дипломных работах часто формулировали все так, чтобы было как можно непонятнее и нельзя было придраться. Нашлась и неплохая формулировка идеи по-русски – «представление данных в удобном для клиента формате». Справедливости ради надо отметить, что, пока я формулировал свои доводы о нелогичности названия, увидел в нем некоторую логику, по крайней мере, в английском варианте.
Важно понимать, что REST – это не протокол и не стандарт, а архитектурный стиль. У этого стиля есть свои принципы. Позволю себе скопировать их с понравившегося источника и прокомментировать.
- Give every “thing” an ID.
Очччень желательно. - Link things together.
Например, в страницу (представление) о Mercedes C218 хорошо бы добавить ссылку на страницу конкретно о двигателе данной модели, чтобы желающие могли сразу туда перейти, а не тратить время на поиск этой самой страницы. - Use standard methods.
Имеется в виду, экономьте свои силы и деньги заказчика, используйте стандартные методы HTTP, например GET http://www.example.com/cars/00345 для получения данных вместо определения собственных методов вроде getCar?id=00345. - Resources can have multiple representations.
Одни и те же данные можно вернуть в XML или JSON для программной обработки или обернутыми в красивый дизайн для просмотра человеком. - Communicate statelessly.
Да, RESTful сервис должен быть как идеальный суд – его не должно интересовать ни прошлое подсудимого (клиента), ни будущее – он просто выносит приговор (отвечает на запрос).
Только что употребленный термин RESTful (веб-)сервис всего лишь означает сервис, реализованный с использованием принципов REST. Так что же нам дает следование эти самым принципам REST? Для начала я бы назвал простоту основным преимуществом архитектуры REST. Простоту идеи, простоту разработки и добавления функциональности к RESTful-приложениям. Идея настолько проста и универсальна, что ее даже сложно сначала уловить. Мы не добавляем никакого нового нового слоя в наш и без того многослойный программерский пирог, а просто используем уже давно признанные стандарты. Поэтому чтобы ответить на вопрос о преимуществах и недостатках и чтобы анализ имел больше смысла, предлагаю перейти к сравнению подходов SOAP и REST.
- SOAP – это целое семейство протоколов и стандартов, откуда напрямую вытекает, что это более тяжеловесный и сложный вариант с точки зрения машинной обработки. Поэтому REST работает быстрее.
- SOAP используют HTTP как транспортный протокол, в то время как REST базируется на нем. Это означает, что все существующие наработки на базе протокола HTTP, такие как кеширование на уровне сервера, масштабирование, продолжают так же работать в REST архитектуре, а для SOAP необходимо искать другие средства. Взамен этого SOAP сервисы получают такое мифическое свойство, как возможность работать с любым протоколом транспортного уровня вместо HTTP, однако практической пользы от него зачастую не больше, чем сотрудникам Челябинского трубопрокатного завода от большого количества статей в википедиях на мертвых языках
- Есть мнение, что разработка RESTful сервисов намного проще. Наверное, это правда, если использовать Notepad в качестве основной среды разработки, но вот с использованием наших чудесных средств разработки, я позволю себе усомниться в верности этого утверждения.
- В первом гугловском результате по запросу «REST vs SOAP» акцентируется внимание на том, что ответ REST может быть представлен в различных форматах, а SOAP привязан к XML. Это действительно важный фактор, достаточно представить себе вызов сервиса из javascript, ответ на который мы определенно хотим получать в JSON.
- «REST vs SOAP» можно перефразировать в «Простота vs Стандарты», что проявляется в том, что для SOAP мы имеем протокол WSDL для исчерпывающего описания веб-сервиса, который с использованием все тех же чудесных средств разработки прото-таки волшебным образом делает почти всю работу за нас. Со стороны REST мы имеем загадочный и неиспользуемый протокол WADL, который в принципе и не нужен – он мешает простоте.
- Второй аспект предыдущего пункта – обработка ошибок. В SOAP она полностью стандартизована, а REST может использовать давно известные коды ошибок HTTP (если здесь Вас посетила мысль, что это же очевидно и зачем я это пишу, то значит Вы внимательно читаете статью).
- То, с чего можно было бы начать, но я припас напоследок. Это одна из ключевых мыслей. SOAP работает с операциями, а REST – с ресурсами. Этот факт в совокупности с отсутствием клиентского состояния у RESTful сервисов приводит нас к тому, что такие вещи как транзакции или другая сложная логика должна реализовываться «SOAP-но». Приведу пару примеров на понимание разницы между подходами. Букмекерская контора заказала сервис для работы с футбольной статистикой. Пользовательский функционал – получить список матчей, получить детали о матче. Для редакторов – редактировать (Create, Edit, Delete) список матчей, редактировать детали матча. Для такой задачи однозначно надо выбирать подход REST и получать бенефиты от его простоты и естественности во взаимодействии с HTTP. Не нужны нам здесь SOAP-конверты, SOAP-главпочтамты и SOAP-авиапочта, которая может использовать любую марку самолета. Нам всего лишь надо реализовать следующее:
Что происходит при обращении с использованием методов HTTP
URL | GET | POST | PUT | DELETE |
example.com/matches | Получаем список матчей | Создаем заново список матчей | Обновляем список матчей | Мстим директору букмекерской конторы |
example.com/matches/28 | Получаем детали матча с ID=28 | Создаем информацию о матче | Обновляем детали матча | Удаляем матч |
Все очень просто! Теперь пример посложнее. Та же букмекерская контора захотела API для ставок на live матчи. Эта процедура включает в себя многочисленные проверки, например, продолжает ли ставка быть актуальной, не изменился ли коэффициент, не превышена ли максимальная сумма ставки для маркета. После этого происходит денежная транзакция, результаты которой записываются в основную и в резервные базы данных. Лишь после этого клиенту приходит ответ об успешности операции. Здесь явно прослеживается ориентация на операции, имеются повышенные требования к безопасности и устойчивости приложения, поэтому целесообразно использовать SOAP.
И еще пару задач для того, чтобы почувствовать тему:
- Футбольный клуб заказывает CMS для подробных сведений об игроках команды-неприятеля. Нужен функционал добавления характеристик игрока простыми пользователями прямо во время матча с последующей интеграцией с табло стадиона, на котором необходимо в реальном времени отображать комментарии.
- Мексиканский наркобарон Педро Гонсалес заказывает API для учета продаж героина в Юго-Западных штатах США. Он особо просит мобильное приложение под эту задачу, т.к. его бизнес часто проходит на открытом воздухе, где нету других вариантов выхода в сеть.
- Анонимный миллиардер очень хочет такую программу, которая бы ему показывала всех его любовниц в городе, в котором он сейчас находится и то, какой текущий статус отношений. Он хочет интегрировать эту программу с уже существующим его личным десктопным приложением для подбора мест для отдыха, он очень хочет большую красную надпись о возможных неприятностях в окошке, где предлагаются варианты авиаперелета.
Какие подходы вы бы использовали в данных задачах? Хотел я еще написать про то, что это все дает .NET разработчику и как это использовать в своих целях, однако вижу, что индекс нудности статьи приближается к критическому, поэтому ограничусь анонсом семинара, который будет продолжением данной статьи и планируется вскоре после выхода номера газеты. С целью понижения все того же показателя я намеренно избегал аспектов безопасности и, например, ответа на вопрос ”А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?”. А выводы статьи будут следующими:
- Филдинг со своими принципами REST ничего не изобрел, а просто собрал в одну диссертацию то, что уже существовало в каком-то виде и изложил то, как можно получать максимальную выгоду из уже сформировавшейся архитектуры сети.
- SOAP и REST – не конкуренты. Они представляют разные весовые категории и вряд ли найдется задача, для которой будет сложно сказать, какой подход рациональнее использовать – SOAP или REST. Поэтому «религиозные» убеждения в вопросах выбора архитектуры для веб-сервиса вряд ли будут полезны. Для тех, кто не знает, с чего начать анализ задачи, могу порекомендовать эту презентацию. У них чаще побеждает REST.
Изучение модели домена JIRA Service Desk с помощью API REST
Это руководство поможет вам понять модель домена JIRA Service Desk, используя API REST JIRA Service Desk и API REST платформы JIRA для его изучения. Служба JIRA Service Desk построена на платформе JIRA, поэтому также будут обсуждаться объекты ключевого домена платформы JIRA.
Вы должны начать с чтения раздела «Обзор». Каждый раздел после этого охватывает разные объекты в модели домена JIRA Service Desk. Мы рекомендуем вам прочитать все эти разделы сверху вниз, но вы можете прочитать их в другом порядке или пропустить разделы, если хотите.
Если вы хотите просмотреть API REST для JIRA Service Desk или JIRA-платформы, вы можете найти их здесь: JIRA API.
Прежде чем вы начнете
- Вы можете использовать любой клиент REST для работы с примерами этого урока. Примеры были написаны с использованием инструмента завитка. Мы также передали результаты через Python, чтобы облегчить чтение ответов JSON.
- Примеры в этом руководстве были в последний раз протестированы с JIRA Service Desk 3.1.
Обзор
Философия проектирования — конкретные версии общих объектов домена
Объекты домена JIRA Service Desk построены на основе одноранговых платформ JIRA. Например, служебные столы основаны на проектах. Однако объекты JIRA Service Desk имеют гораздо более конкретную цель по сравнению с объектами платформы JIRA. Например, у вас может быть тип запроса «Покупка ноутбука» в JIRA Service Desk, который имеет гораздо более конкретный вариант использования, чем «Тип задачи» Задача (на платформе JIRA), на котором он основан.
Причиной этого является то, что ключевая цель дизайна JIRA Service Desk — иметь простой и целенаправленный опыт для людей, обращающихся за помощью в службу поддержки. Платформа JIRA должна обслуживать множество различных пользовательских опытов, и, как результат, у нее есть общие объекты домена, которые являются более гибкими. Однако эти общие понятия и термины могут не иметь смысла для клиентов службы поддержки. Поэтому JIRA Service Desk сопоставляет общие объекты с конкретными объектами службы JIRA Service Desk. Например, вы можете сопоставить поле задачи «Резюме» (платформа JIRA) с полем типа запроса, которое вы можете назвать «Что вам нужно?». Одно и то же поле имеет двойную цель — оно по-прежнему функционирует как поле «Резюме», но оно представлено как поле «Что вам нужно?».
Если вы понимаете эту философию дизайна, которая лежит в основе того, как платформа JIRA и JIRA Service Desk соотносятся друг с другом, модель домена JIRA Service Desk будет иметь больше смысла.
Резюме объектов домена
РИСУНОК
В этом разделе описываются ключевые объекты домена в JIRA Service Desk, а также соответствующие объекты на платформе JIRA. В приведенной ниже таблице описаны объекты на высоком уровне. Мы рассмотрим каждый объект более подробно, используя API REST, в последующих разделах этой страницы.
Служба поддержки (Служба поддержки JIRA)
- Служебные столы являются «контейнерами» верхнего уровня в JSD и содержат конфигурацию для конкретной службы поддержки. Примером может служить ваша служба технической поддержки.
- Одноранговым объектом для Service Desk является проект. Существует сопоставление 1: 1 между службой поддержки и проектом.
Проект (платформа JIRA)
- Проект представляет собой просто набор задач. В JIRA Service Desk конфигурация, специфичная для платформы JIRA (например, рабочий процесс, разрешения и т. д.), определяется с точки зрения проекта, а не службы поддержки.
- Одноранговым объектом для Проекта является Служба поддержки.
Запрос (Служба поддержки JIRA)
- Запрос (Request) содержит данные, когда клиент запрашивает помощь у команды службы поддержки. Примером может служить запрос клиента на новую учетную запись электронной почты.
- Запрос (Request) состоит из нескольких полей запроса.
- Одноранговым объектом для запроса является задача. Запросы выполняются с точки зрения задач. Запрос(Request) должен быть задачей, хотя задача может быть не Запросом(Request).
Задача (платформа JIRA)
- Задача — это самый маленький контейнер данных на платформе JIRA и может представлять разные вещи (например, ошибку, задачу, запрос(request) и т. д.) В зависимости от того, как организация использует JIRA.
- Задача состоит из нескольких полей задач и имеет «ключ задачи» (полученный из ключа Project), который является уникальным для экземпляра JIRA.
- Одноранговым объектом для задачи является запрос (request) .
Поле запроса (Служба поддержки JIRA)
- Поле запроса — это информация, которую вы хотите записать в запросах(Requests). Поля запроса реализованы с точки зрения полей задач.
- Вы можете рассматривать поля запроса как логическое «представление» по полям задач, которые позволяют переименовать общие поля JIRA на язык, который ваши клиенты поймут. Например, у вас может быть поле запроса «Что вам нужно?», Которое основано на поле задач «Резюме».
- Одноранговым объектом для поля запроса является поле «Задача».
Поле задач (платформа JIRA)
- Поля «Задача» — это «именованные» значения, содержащиеся в «Задачах». Например, резюме задач, дата, статус и т. д.
- Одноранговым объектом для поля «Задача» является поле «Запрос».
Комментарий (платформа JIRA и сервисный центр JIRA)
- Комментарии прилагаются к запросам / задачам и представляют собой разговор, связанный с обслуживанием запросов.
Тип запроса (JIRA Service Desk)
- Тип запроса определяет информацию, которая должна быть захвачена для определенного типа запросов. Вы можете думать о них как о способе категоризации запросов в Service Desk. Например, у вас может быть тип запроса «Системный доступ» или тип запроса «Покупка ноутбука».
- Одноранговым объектом для типа запроса является Тип задачи, однако типы запросов и типы задач не равны 1: 1. Различные типы запросов могут быть определены для одного и того же типа задач. Индивидуальный запрос / задача всегда будет иметь один тип запроса.
Тип задачи (платформа JIRA)
- Тип задачи используется на платформе для отображения конфигурации JIRA, например полей и рабочих процессов, в «Задачи».
- Одноранговым объектом для типа задачи является Тип запроса. Индивидуальный запрос / задача всегда будет иметь один тип задачи.
Статус запроса (Служба поддержки JIRA)
- Статус запроса представляет текущее состояние запроса. Клиенты JIRA Service Desk могут видеть состояние запроса из статуса запроса.
- Статус запроса основан на статусе задачи. Например, у вас может быть статус запроса «Завершенный», который основан на «Решенном» статусе задачи.
- Одноранговым объектом для статуса запроса является статус задачи.
Статус задачи (платформа JIRA)
- Статус задачи представляет состояние задачи внутри ее определенного рабочего процесса JIRA. Не все статусы задач отображаются клиентам JIRA Service Desk — возможно, что есть шаги рабочего процесса, которые видны только команде службы поддержки.
- Одноранговым объектом для статуса задач является статус запроса.
Соглашение об уровне обслуживания запросов (JIRA Service Desk)
- SLA запроса используется для отслеживания показателей того, сколько времени тратится на обслуживание запросов. Таймеры устанавливаются, когда Запросы вводят определенные условия, и цели определены для перемещения этих Запросов в и из условий. Например, у вас может быть определено SLA «Время от первого ответа», так что ваша команда может стремиться вернуться к клиенту в течение 4 часов с момента подачи запроса.
- Отсутствует одноранговый объект для соглашения об уровне обслуживания запросов
Сервисные столы и проекты
Основным контейнером объектов домена JIRA Service Desk является Service Desk и его одноранговый объект — проект платформы JIRA. Между Службой поддержки и Проектом существует индивидуальная связь; и Service Desk реализуется из проекта платформы JIRA. Разрешения для управления пользователями, которые могут получить доступ к службе поддержки, контролируются через одноранговый проект.
Служба поддержки является отправной точкой для всех вещей в JIRA Service Desk. Он содержит большинство других объектов домена, таких как типы запросов, поля типа запроса и т. д. Давайте посмотрим, как выглядит Служба поддержки, путем получения списка сервисных столов в системе через REST API:
Пример запроса A
curl -H "X-ExperimentalApi: true" -u agent:agent -X GET "http://localhost:2990/jira/rest/servicedeskapi/servicedesk?start=0&limit=5" | python -mjson.tool
Ответ
{
"_links": {
"base": "http://localhost:2990/jira",
"context": "/jira",
"next": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk?limit=5&start=5",
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk?start=0&limit=5"
},
"isLastPage": false,
"limit": 5,
"size": 5,
"start": 0,
"values": [
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/15"
},
"id": 15,
"projectId": 11041,
"projectName": "All Teams Service Desk"
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/19"
},
"id": 19,
"projectId": 11241,
"projectName": "Foundation Leave"
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/21"
},
"id": 21,
"projectId": 11243,
"projectName": "Human Resources Service Desk"
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/16"
},
"id": 16,
"projectId": 11042,
"projectName": "IT Help"
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/23"
},
"id": 23,
"projectId": 11245,
"projectName": "Lawyer Up - Company Lawyer Requests"
}
]
}
Вот несколько замечаний о службе поддержки:
- У каждой службы поддержки есть Id, JIRA projectId и projectName.
- ProjectId происходит от объекта Project домена платформы JIRA. Вы можете получить дополнительную информацию о проекте через JIRA Platform REST API. Во многих случаях вы можете использовать JIRA Service Desk REST API или JIRA Platform REST API для поиска той же информации — когда использовать какой API зависит от вашего варианта использования и того, что вы хотите знать.
- Раздел * _links * вверху содержит полезные URL-адреса URI, которые указывают другие места в системе, такие как базовый URL платформы JIRA.
- JIRA Service Desk REST API использует перелистование для списков ресурсов. В этом случае мы попросили 5 на странице, начиная с 0; то есть первые пять служебных столов. Ссылка * next * будет использоваться для получения следующего набора элементов в списке.
Из ответа можно видеть, что существует прямая связь между Service Desk и его равноправным проектом. Давайте рассмотрим это дальше, получив информацию о проекте для одной из служебных столов через API REST: «Служба обслуживания всех команд» (projectId = 11041):
Пример запроса B
curl -H "X-ExperimentalApi: true" -u agent:agent -X GET "http://localhost:2990/jira/rest/api/2/project/11041" | python -mjson.tool
Ответ
{
"assigneeType": "UNASSIGNED",
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/projectavatar?size=xsmall&avatarId=10873",
"24x24": "http://localhost:2990/jira/secure/projectavatar?size=small&avatarId=10873",
"32x32": "http://localhost:2990/jira/secure/projectavatar?size=medium&avatarId=10873",
"48x48": "http://localhost:2990/jira/secure/projectavatar?avatarId=10873"
},
"components": [
{
"description": "Issues related to the intranet. Created by JIRA Service Desk.",
"id": "10414",
"isAssigneeTypeValid": false,
"name": "Intranet",
"self": "http://localhost:2990/jira/rest/api/2/component/10414"
},
{
"description": "Issues related to JIRA. Created by JIRA Service Desk.",
"id": "10413",
"isAssigneeTypeValid": false,
"name": "JIRA",
"self": "http://localhost:2990/jira/rest/api/2/component/10413"
},
{
"description": "Issues related to the public website. Created by JIRA Service Desk.",
"id": "10415",
"isAssigneeTypeValid": false,
"name": "Public website",
"self": "http://localhost:2990/jira/rest/api/2/component/10415"
}
],
"description": "",
"expand": "description,lead,url,projectKeys",
"id": "11041",
"issueTypes": [
{
"description": "For general IT problems and questions. Created by JIRA Service Desk.",
"iconUrl": "http://localhost:2990/jira/servicedesk/issue-type-icons?icon=it-help",
"id": "13",
"name": "IT Help",
"self": "http://localhost:2990/jira/rest/api/2/issuetype/13",
"subtask": false
},
{
"description": "Track items that need to be bought. Created by JIRA Service Desk.",
"iconUrl": "http://localhost:2990/jira/servicedesk/issue-type-icons?icon=purchase",
"id": "14",
"name": "Purchase",
"self": "http://localhost:2990/jira/rest/api/2/issuetype/14",
"subtask": false
},
{
"description": "Track system outages or incidents. Created by JIRA Service Desk.",
"iconUrl": "http://localhost:2990/jira/servicedesk/issue-type-icons?icon=fault",
"id": "16",
"name": "Fault",
"self": "http://localhost:2990/jira/rest/api/2/issuetype/16",
"subtask": false
},
{
"description": "For new system accounts or passwords. Created by JIRA Service Desk.",
"iconUrl": "http://localhost:2990/jira/servicedesk/issue-type-icons?icon=access",
"id": "17",
"name": "Access",
"self": "http://localhost:2990/jira/rest/api/2/issuetype/17",
"subtask": false
}
],
"key": "SD",
"lead": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Project Admin of some projects",
"key": "patricia",
"name": "projectad",
"self": "http://localhost:2990/jira/rest/api/2/user?username=projectad"
},
"name": "All Teams Service Desk",
"projectTypeKey": "service_desk",
"roles": {
"Administrators": "http://localhost:2990/jira/rest/api/2/project/11041/role/10002",
"Developers": "http://localhost:2990/jira/rest/api/2/project/11041/role/10001",
"Doco Team": "http://localhost:2990/jira/rest/api/2/project/11041/role/10010",
"Service Desk Collaborators": "http://localhost:2990/jira/rest/api/2/project/11041/role/10210",
"Service Desk Customers": "http://localhost:2990/jira/rest/api/2/project/11041/role/10310",
"Service Desk Team": "http://localhost:2990/jira/rest/api/2/project/11041/role/10111",
"Users": "http://localhost:2990/jira/rest/api/2/project/11041/role/10000"
},
"self": "http://localhost:2990/jira/rest/api/2/project/11041",
"versions": []
}
Как вы можете видеть, есть много дополнительной информации о проекте, которую вы можете получить с помощью REST API платформы JIRA. Сюда входят объекты домена, такие как типы задач, компоненты и т. д. Мы не будем здесь подробно обсуждать это, но если вы хотите узнать больше, ознакомьтесь с документацией REST API на ресурсе проекта.
Запросы и задачи
Когда кто-то запрашивает помощь у службы поддержки, которая называется Запросом. В запросе также имеется равноправный объект: задача. Запросы выполняются с помощью задач, так же как и службы поддержки, реализованные из проектов. Однако не все задачи — это запросы. Это связано с тем, что JIRA может использоваться для других целей, таких как JIRA Software и JIRA Core. Основное правило заключается в том, что все, что создается через портал службы поддержки, считается запросом.
Запросы могут быть рассмотрены с точки зрения лица, сообщившего о них. Мы рассмотрим несколько примеров с точки зрения клиента (названного «Ronald the Customer»). Мы увидим, как они будут использовать REST API JIRA Service Desk для получения информации о запросах, которые они создали.
В первом примере показано, как клиент будет извлекать все запросы, что они создали:
Пример запроса C
curl -H "X-ExperimentalApi: true" -u customer:customer -X GET "http://localhost:2990/jira/rest/servicedeskapi/request" | python -mjson.tool
Ответ
{
"_links": {
"base": "http://localhost:2990/jira",
"context": "/jira",
"self": "http://localhost:2990/jira/rest/servicedeskapi/request"
},
"expand": "customerRequest.participant,customerRequest.status,customerRequest.sla,requestType,serviceDesk",
"isLastPage": true,
"limit": 50,
"size": 3,
"start": 0,
"values": [
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17229"
},
"createdDate": {
"epochMillis": 1446776670000,
"friendly": "06/Nov/15 1:24 PM",
"iso8601": "2015-11-06T13:24:30+1100"
},
"currentStatus": {
"status": "Resolved",
"statusDate": {
"epochMillis": 1446776741021,
"friendly": "06/Nov/15 1:25 PM",
"iso8601": "2015-11-06T13:25:41+1100"
}
},
"expand": "customerRequest.participant,customerRequest.status,customerRequest.sla,requestType,serviceDesk",
"issueId": 17229,
"issueKey": "SD-12",
"issueTypeId": "17",
"projectId": 11041,
"reporter": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"requestFieldValues": [
{
"fieldId": "components",
"label": "Which system?",
"value": [
{
"description": "Issues related to JIRA. Created by JIRA Service Desk.",
"id": "10413",
"name": "JIRA",
"self": "http://localhost:2990/jira/rest/api/2/component/10413"
}
]
},
{
"fieldId": "summary",
"label": "What type of access do you need?",
"value": "root access"
},
{
"fieldId": "description",
"label": "Why do you need this?",
"value": "I want to be able to do stuff on JIRA. Giving me root access seems like a good way to do that."
}
],
"requestTypeId": 63,
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17229",
"serviceDeskId": 15
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17228"
},
"createdDate": {
"epochMillis": 1446769068000,
"friendly": "06/Nov/15 11:17 AM",
"iso8601": "2015-11-06T11:17:48+1100"
},
"currentStatus": {
"status": "Resolved",
"statusDate": {
"epochMillis": 1446776578551,
"friendly": "06/Nov/15 1:22 PM",
"iso8601": "2015-11-06T13:22:58+1100"
}
},
"expand": "customerRequest.participant,customerRequest.status,customerRequest.sla,requestType,serviceDesk",
"issueId": 17228,
"issueKey": "SD-11",
"issueTypeId": "17",
"projectId": 11041,
"reporter": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"requestFieldValues": [
{
"fieldId": "components",
"label": "Which system?",
"value": [
{
"description": "Issues related to the public website. Created by JIRA Service Desk.",
"id": "10415",
"name": "Public website",
"self": "http://localhost:2990/jira/rest/api/2/component/10415"
}
]
},
{
"fieldId": "summary",
"label": "What type of access do you need?",
"value": "I need basic login access"
},
{
"fieldId": "description",
"label": "Why do you need this?",
"value": "I have joined the Marketing Zoom team and I need access to the Content Management system to update our public messaging."
}
],
"requestTypeId": 63,
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17228",
"serviceDeskId": 15
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227"
},
"createdDate": {
"epochMillis": 1446768040000,
"friendly": "06/Nov/15 11:00 AM",
"iso8601": "2015-11-06T11:00:40+1100"
},
"currentStatus": {
"status": "Waiting for Support",
"statusDate": {
"epochMillis": 1446768682499,
"friendly": "06/Nov/15 11:11 AM",
"iso8601": "2015-11-06T11:11:22+1100"
}
},
"expand": "customerRequest.participant,customerRequest.status,customerRequest.sla,requestType,serviceDesk",
"issueId": 17227,
"issueKey": "SD-10",
"issueTypeId": "13",
"projectId": 11041,
"reporter": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"requestFieldValues": [
{
"fieldId": "summary",
"label": "What do you need?",
"value": "I need help with the L8 printer"
},
{
"fieldId": "description",
"label": "Why do you need this?",
"value": "Its not printing at all. I have changed the cartridge and pressed reset but not deal.\n\nI am at a loss as to what to do next"
},
{
"fieldId": "customfield_11440",
"label": "Your Office?"
}
],
"requestTypeId": 62,
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227",
"serviceDeskId": 15
}
]
}
Давайте рассмотрим следующие элементы данных:
"issueId": 17229,
"issueKey": "SD-12",
Записи issueId и issueKey представляют собой идентификатор и ключ задачи платформы JIRA используемой для представления этого запроса. Вы можете использовать API REST платформы JIRA, чтобы узнать еще об этой задаче, как показано ниже:
Пример запроса D
curl -H "X-ExperimentalApi: true" -u agent:agent -X GET "http://localhost:2990/jira/rest/api/2/issue/17227" | python -mjson.tool
Ответ
{
"expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog,versionedRepresentations",
"fields": {
"aggregateprogress": {
"progress": 0,
"total": 0
},
"aggregatetimeestimate": null,
"aggregatetimeoriginalestimate": null,
"aggregatetimespent": null,
"assignee": null,
"attachment": [],
"comment": {
"comments": [
{
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Hi Customer X,\n\nWe have received your request. We are about to head our to the company all hands and will get back to you as soon as we can\n\n\u2013 \u00aagent\u2122",
"created": "2015-11-06T11:02:04.601+1100",
"id": "37860",
"self": "http://localhost:2990/jira/rest/api/2/issue/17227/comment/37860",
"updateAuthor": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"updated": "2015-11-06T11:02:04.601+1100"
},
{
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"body": "Ahh good point. I too will be there so I will maybe see you there.",
"created": "2015-11-06T11:02:41.960+1100",
"id": "37861",
"self": "http://localhost:2990/jira/rest/api/2/issue/17227/comment/37861",
"updateAuthor": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"updated": "2015-11-06T11:02:41.960+1100"
},
{
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Hi Customer X,\n\nOk I went up to Level 8 to check on the printer but the floor is being renovated as part of the new building works. I am guessing your are on another level. Our directory service is down right now so can you please tell me what floor you are and also can you tell me what operating system you are running.\n\n\u2013 \u00aagent\u2122",
"created": "2015-11-06T11:09:34.272+1100",
"id": "37862",
"self": "http://localhost:2990/jira/rest/api/2/issue/17227/comment/37862",
"updateAuthor": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"updated": "2015-11-06T11:09:34.272+1100"
},
{
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"body": "I am on level 7 sorry, in the east wing. How do I find out what operating system I have? Is that the Internet browser I am using? Because I think thats just called Safari.",
"created": "2015-11-06T11:11:22.404+1100",
"id": "37863",
"self": "http://localhost:2990/jira/rest/api/2/issue/17227/comment/37863",
"updateAuthor": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"updated": "2015-11-06T11:11:22.404+1100"
},
{
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "\nNote to team - we need to get the directory service back up and running. We cant find out what floor any one is on without.\n",
"created": "2015-11-06T11:12:27.488+1100",
"id": "37864",
"self": "http://localhost:2990/jira/rest/api/2/issue/17227/comment/37864",
"updateAuthor": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"updated": "2015-11-06T11:12:27.488+1100"
},
{
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Also whats up with all the dust coming down the stair well with the new renovations. If it gets into the server room there will be hell to pay.",
"created": "2015-11-06T11:13:22.477+1100",
"id": "37865",
"self": "http://localhost:2990/jira/rest/api/2/issue/17227/comment/37865",
"updateAuthor": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"updated": "2015-11-06T11:13:22.477+1100"
}
],
"maxResults": 6,
"startAt": 0,
"total": 6
},
"components": [],
"created": "2015-11-06T11:00:40.459+1100",
"creator": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"customfield_10001": null,
"customfield_10010": null,
"customfield_10020": null,
"customfield_10022": null,
"customfield_10040": null,
"customfield_10050": null,
"customfield_10051": null,
"customfield_10071": null,
"customfield_10080": null,
"customfield_10090": null,
"customfield_10100": null,
"customfield_10110": null,
"customfield_10120": null,
"customfield_10144": null,
"customfield_10540": null,
"customfield_10541": "She sells sea shells.",
"customfield_10641": null,
"customfield_10642": null,
"customfield_10740": null,
"customfield_11040": {
"_links": {
"jiraRest": "http://localhost:2990/jira/rest/api/2/issue/17227",
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227"
},
"currentStatus": {
"status": "Waiting for Support",
"statusDate": {
"epochMillis": 1446768682499,
"friendly": "06/Nov/15 11:11 AM",
"iso8601": "2015-11-06T11:11:22+1100"
}
},
"requestType": {
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/15/requesttype/62"
},
"description": "Get assistance for general IT problems and questions [example]",
"id": 62,
"name": "Get IT help",
"serviceDeskId": 15
}
},
"customfield_11043": {
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/sla/30"
},
"completedCycles": [],
"id": 30,
"name": "Time to resolution",
"ongoingCycle": {
"breachTime": {
"epochMillis": 1446789600000,
"friendly": "06/Nov/15 5:00 PM",
"iso8601": "2015-11-06T17:00:00+1100"
},
"breached": true,
"elapsedTime": {
"friendly": "136h 18m",
"millis": 490681509
},
"goalDuration": {
"friendly": "4h",
"millis": 14400000
},
"paused": false,
"remainingTime": {
"friendly": "-132h 18m",
"millis": -476281509
},
"startTime": {
"epochMillis": 1446768040477,
"friendly": "06/Nov/15 11:00 AM",
"iso8601": "2015-11-06T11:00:40+1100"
},
"withinCalendarHours": true
}
},
"customfield_11044": {
"errorMessage": "metric not found"
},
"customfield_11045": {
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/sla/43"
},
"completedCycles": [
{
"breached": false,
"elapsedTime": {
"friendly": "0m",
"millis": 0
},
"goalDuration": {
"friendly": "15m",
"millis": 900000
},
"remainingTime": {
"friendly": "15m",
"millis": 900000
},
"startTime": {
"epochMillis": 1446768040477,
"friendly": "06/Nov/15 11:00 AM",
"iso8601": "2015-11-06T11:00:40+1100"
},
"stopTime": {
"epochMillis": 1446768124651,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:04+1100"
}
},
{
"breached": false,
"elapsedTime": {
"friendly": "0m",
"millis": 0
},
"goalDuration": {
"friendly": "15m",
"millis": 900000
},
"remainingTime": {
"friendly": "15m",
"millis": 900000
},
"startTime": {
"epochMillis": 1446768162075,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:42+1100"
},
"stopTime": {
"epochMillis": 1446768574276,
"friendly": "06/Nov/15 11:09 AM",
"iso8601": "2015-11-06T11:09:34+1100"
}
}
],
"id": 43,
"name": "Time waiting for support",
"ongoingCycle": {
"breachTime": {
"epochMillis": 1446776100000,
"friendly": "06/Nov/15 1:15 PM",
"iso8601": "2015-11-06T13:15:00+1100"
},
"breached": true,
"elapsedTime": {
"friendly": "136h 18m",
"millis": 490681521
},
"goalDuration": {
"friendly": "15m",
"millis": 900000
},
"paused": false,
"remainingTime": {
"friendly": "-136h 3m",
"millis": -489781521
},
"startTime": {
"epochMillis": 1446768682500,
"friendly": "06/Nov/15 11:11 AM",
"iso8601": "2015-11-06T11:11:22+1100"
},
"withinCalendarHours": true
}
},
"customfield_11046": null,
"customfield_11047": null,
"customfield_11140": [],
"customfield_11340": null,
"customfield_11341": null,
"customfield_11440": null,
"description": "Its not printing at all. I have changed the cartridge and pressed reset but not deal.\n\nI am at a loss as to what to do next",
"duedate": null,
"environment": null,
"fixVersions": [],
"issuelinks": [],
"issuetype": {
"description": "For general IT problems and questions. Created by JIRA Service Desk.",
"iconUrl": "http://localhost:2990/jira/servicedesk/issue-type-icons?icon=it-help",
"id": "13",
"name": "IT Help",
"self": "http://localhost:2990/jira/rest/api/2/issuetype/13",
"subtask": false
},
"labels": [],
"lastViewed": "2015-11-06T13:24:34.643+1100",
"priority": {
"iconUrl": "http://localhost:2990/jira/images/icons/priorities/major.svg",
"id": "3",
"name": "Major",
"self": "http://localhost:2990/jira/rest/api/2/priority/3"
},
"progress": {
"progress": 0,
"total": 0
},
"project": {
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/projectavatar?size=xsmall&avatarId=10873",
"24x24": "http://localhost:2990/jira/secure/projectavatar?size=small&avatarId=10873",
"32x32": "http://localhost:2990/jira/secure/projectavatar?size=medium&avatarId=10873",
"48x48": "http://localhost:2990/jira/secure/projectavatar?avatarId=10873"
},
"id": "11041",
"key": "SD",
"name": "All Teams Service Desk",
"self": "http://localhost:2990/jira/rest/api/2/project/11041"
},
"reporter": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"resolution": null,
"resolutiondate": null,
"status": {
"description": "This was auto-generated by JIRA Service Desk during workflow import",
"iconUrl": "http://localhost:2990/jira/images/icons/statuses/generic.png",
"id": "10021",
"name": "Waiting for Support",
"self": "http://localhost:2990/jira/rest/api/2/status/10021",
"statusCategory": {
"colorName": "yellow",
"id": 4,
"key": "indeterminate",
"name": "In Progress",
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/4"
}
},
"subtasks": [],
"summary": "I need help with the L8 printer",
"timeestimate": null,
"timeoriginalestimate": null,
"timespent": null,
"timetracking": {},
"updated": "2015-11-06T11:13:22.477+1100",
"versions": [],
"votes": {
"hasVoted": false,
"self": "http://localhost:2990/jira/rest/api/2/issue/SD-10/votes",
"votes": 0
},
"watches": {
"isWatching": true,
"self": "http://localhost:2990/jira/rest/api/2/issue/SD-10/watchers",
"watchCount": 1
},
"worklog": {
"maxResults": 20,
"startAt": 0,
"total": 0,
"worklogs": []
},
"workratio": -1
},
"id": "17227",
"key": "SD-10",
"self": "http://localhost:2990/jira/rest/api/2/issue/17227"
}
Глядя на эти данные, вы можете увидеть поля, записанные по этой задаче. Сравните то, как значения поля JIRA Service Desk (Службы поддержки) отличаются в представлении своим партнерам платформы JIRA, как показано ниже:
Служба поддержки JIRA:
"requestFieldValues": [
{
"fieldId": "summary",
"label": "What do you need?",
"value": "I need help with the L8 printer"
},
{
"fieldId": "description",
"label": "Why do you need this?",
"value": "Its not printing at all. I have
changed the cartridge and pressed
reset.\r\n\r\nI am at a loss as
to what to do next"
}
Платформа JIRA:
"description": "Its not printing at all. I
have changed the cartridge and pressed
reset.\r\n\r\nI am at a loss as to what
to do next",
"summary": "I need help with the L8 printer",
Вы заметите, что мы обратились к запросу в качестве пользовательского «клиента» с помощью REST API JIRA Service Desk, но мы переключились на «агент» пользователя при использовании REST API платформы JIRA. Это связано с тем, как работает лицензирование JIRA Service Desk: клиентам разрешено использовать REST API JIRA Service Desk для бесплатного доступа к их запросам, так же как им разрешено бесплатно пользоваться сайтом службы поддержки JIRA. Однако в обмен на эту нулевую стоимость доллара им не разрешено использовать API JIRA REST (или веб-интерфейс JIRA).
Однако лицензированным агентам службы JIRA Service Desk разрешено использовать оба REST API, поэтому мы переключились на «агент», чтобы получить платформу JIRA для просмотра задачи.
Поля типов запроса и поля типа запроса
Тип запроса определяет, какую информацию вы хотите получить от своих клиентов, когда они обратятся за помощью. Поля типа запроса — это поля, которые вы хотите захватить, и указаны на языке, который лучше понять вашим клиентам.
Если вы хотите создать запрос, то перечисление типов запросов и их полей типа запроса позволит вам сделать это более общим образом.
Пример запроса E
curl -H "X-ExperimentalApi: true" -u customer:customer -X GET "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/15/requesttype" | python -mjson.tool
Ответ
{
"_links": {
"base": "http://localhost:2990/jira",
"context": "/jira",
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/15/requesttype"
},
"isLastPage": true,
"limit": 50,
"size": 2,
"start": 0,
"values": [
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/15/requesttype/62"
},
"description": "Get assistance for general IT problems and questions [example]",
"id": 62,
"name": "Get IT help",
"serviceDeskId": 15
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/15/requesttype/63"
},
"description": "Request a new account for an internal system [example]",
"id": 63,
"name": "Request a new account",
"serviceDeskId": 15
}
]
}
Это показывает, что для этой службы поддержки существует два типа запросов. Давайте рассмотрим обязательные поля для первой, получившей название «Get IT help»
Пример запроса F
curl -H "X-ExperimentalApi: true" -u customer:customer -X GET "http://localhost:2990/jira/rest/servicedeskapi/servicedesk/15/requesttype/62/field" | python -mjson.tool
Ответ
{
"canAddRequestParticipants": true,
"canRaiseOnBehalfOf": false,
"requestTypeFields": [
{
"description": "e.g. 'new mailing list'",
"fieldId": "summary",
"jiraSchema": {
"system": "summary",
"type": "string"
},
"name": "What do you need?",
"required": true,
"validValues": []
},
{
"description": "",
"fieldId": "description",
"jiraSchema": {
"system": "description",
"type": "string"
},
"name": "Why do you need this?",
"required": true,
"validValues": []
},
{
"description": "The best place to find you if we need to chat in person",
"fieldId": "customfield_11440",
"jiraSchema": {
"custom": "com.atlassian.jira.plugin.system.customfieldtypes:select",
"customId": 11440,
"type": "option"
},
"name": "Your Office?",
"required": false,
"validValues": [
{
"children": [],
"label": "Bradfield",
"value": "10320"
},
{
"children": [],
"label": "North Hampton",
"value": "10321"
},
{
"children": [],
"label": "City",
"value": "10322"
}
]
}
]
}
Здесь у нас есть несколько полей типа запроса. Один из наиболее интересных здесь — «customfield_11440». Вот что нужно отметить в этой области:
- Записи jiraSchema рассказывают вам о поле и о том, как оно работает. В этом случае мы можем видеть, что это «выбранное» пользовательское поле, содержащее фиксированный список офисных мест.
- Записи validValues сообщают вам, что считается допустимым значением для этого поля, а также именем и описаниями этого поля. Само поле не является обязательным полем, а это означает, что если вы создали запрос с использованием этого типа запроса,тогда как вам не нужно будет указывать значение. Однако, если вам это нужно, тогда это должно быть одно из допустимых значений.
Комментарии
Вы можете перечислить комментарии, которые были сделаны по запросу. Комментарии приходят в двух вариантах: комментарии общественности и внутренние комментарии. Если клиент (бесплатный) использует REST API, то они будут видеть только публичные комментарии. Однако, если лицензированный агент службы JIRA Service Desk использует REST API, тогда они смогут видеть все комментарии, как общедоступные, так и внутренние. Сравните следующие два вызова REST API, которые извлекают комментарии для запроса:
Клиент получает все комментарии для запроса:
Пример G-запроса
curl -H "X-ExperimentalApi: true" -u customer:customer -X GET "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment" | python -mjson.tool
Ответ
{
"_links": {
"base": "http://localhost:2990/jira",
"context": "/jira",
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment"
},
"isLastPage": true,
"limit": 50,
"size": 4,
"start": 0,
"values": [
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37860"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Hi Customer X,\n\nWe have received your request. We are about to head our to the company all hands and will get back to you as soon as we can\n\n\u2013 \u00aagent\u2122",
"created": {
"epochMillis": 1446768124601,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:04+1100"
},
"id": 37860,
"public": true
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37861"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"body": "Ahh good point. I too will be there so I will maybe see you there.",
"created": {
"epochMillis": 1446768161960,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:41+1100"
},
"id": 37861,
"public": true
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37862"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Hi Customer X,\n\nOk I went up to Level 8 to check on the printer but the floor is being renovated as part of the new building works. I am guessing your are on another level. Our directory service is down right now so can you please tell me what floor you are and also can you tell me what operating system you are running.\n\n\u2013 \u00aagent\u2122",
"created": {
"epochMillis": 1446768574272,
"friendly": "06/Nov/15 11:09 AM",
"iso8601": "2015-11-06T11:09:34+1100"
},
"id": 37862,
"public": true
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37863"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"body": "I am on level 7 sorry, in the east wing. How do I find out what operating system I have? Is that the Internet browser I am using? Because I think thats just called Safari.",
"created": {
"epochMillis": 1446768682404,
"friendly": "06/Nov/15 11:11 AM",
"iso8601": "2015-11-06T11:11:22+1100"
},
"id": 37863,
"public": true
}
]
}
Агент получает все комментарии для запроса:
Пример запроса H
curl -H "X-ExperimentalApi: true" -u agent:agent -X GET "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment" | python -mjson.tool
Ответ
{
"_links": {
"base": "http://localhost:2990/jira",
"context": "/jira",
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment"
},
"isLastPage": true,
"limit": 50,
"size": 6,
"start": 0,
"values": [
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37860"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Hi Customer X,\n\nWe have received your request. We are about to head our to the company all hands and will get back to you as soon as we can\n\n\u2013 \u00aagent\u2122",
"created": {
"epochMillis": 1446768124601,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:04+1100"
},
"id": 37860,
"public": true
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37861"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"body": "Ahh good point. I too will be there so I will maybe see you there.",
"created": {
"epochMillis": 1446768161960,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:41+1100"
},
"id": 37861,
"public": true
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37862"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Hi Customer X,\n\nOk I went up to Level 8 to check on the printer but the floor is being renovated as part of the new building works. I am guessing your are on another level. Our directory service is down right now so can you please tell me what floor you are and also can you tell me what operating system you are running.\n\n\u2013 \u00aagent\u2122",
"created": {
"epochMillis": 1446768574272,
"friendly": "06/Nov/15 11:09 AM",
"iso8601": "2015-11-06T11:09:34+1100"
},
"id": 37862,
"public": true
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37863"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10092",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10092",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10092",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10092"
},
"displayName": "Ronald The Customer",
"emailAddress": "[email protected]",
"key": "ronald",
"name": "customer",
"self": "http://localhost:2990/jira/rest/api/2/user?username=customer",
"timeZone": "Australia/Sydney"
},
"body": "I am on level 7 sorry, in the east wing. How do I find out what operating system I have? Is that the Internet browser I am using? Because I think thats just called Safari.",
"created": {
"epochMillis": 1446768682404,
"friendly": "06/Nov/15 11:11 AM",
"iso8601": "2015-11-06T11:11:22+1100"
},
"id": 37863,
"public": true
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37864"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "\nNote to team - we need to get the directory service back up and running. We cant find out what floor any one is on without.\n",
"created": {
"epochMillis": 1446768747488,
"friendly": "06/Nov/15 11:12 AM",
"iso8601": "2015-11-06T11:12:27+1100"
},
"id": 37864,
"public": false
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/comment/37865"
},
"author": {
"active": true,
"avatarUrls": {
"16x16": "http://localhost:2990/jira/secure/useravatar?size=xsmall&avatarId=10082",
"24x24": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10082",
"32x32": "http://localhost:2990/jira/secure/useravatar?size=medium&avatarId=10082",
"48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10082"
},
"displayName": "\u00aagent\u2122",
"emailAddress": "[email protected]",
"key": "waldo",
"name": "agent",
"self": "http://localhost:2990/jira/rest/api/2/user?username=agent",
"timeZone": "Australia/Sydney"
},
"body": "Also whats up with all the dust coming down the stair well with the new renovations. If it gets into the server room there will be hell to pay.",
"created": {
"epochMillis": 1446768802477,
"friendly": "06/Nov/15 11:13 AM",
"iso8601": "2015-11-06T11:13:22+1100"
},
"id": 37865,
"public": false
}
]
}
Статусы запросов
Запрос может несколько раз изменять статус, когда вы пытаетесь помочь клиенту. Каждый раз, когда это происходит, клиент сможет увидеть, в каком состоянии находится запрос. Ниже приведен пример запроса, который был повторно открыт после того, как он считался обработанным:
Пример I Запрос
curl -H "X-ExperimentalApi: true" -u customer:customer -X GET "http://localhost:2990/jira/rest/servicedeskapi/request/17227/status" | python -mjson.tool
Ответ
{
"_links": {
"base": "http://localhost:2990/jira",
"context": "/jira",
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/status"
},
"isLastPage": true,
"limit": 50,
"size": 4,
"start": 0,
"values": [
{
"status": "Waiting for Support",
"statusDate": {
"epochMillis": 1446768682499,
"friendly": "06/Nov/15 11:11 AM",
"iso8601": "2015-11-06T11:11:22+1100"
}
},
{
"status": "Waiting for Customer",
"statusDate": {
"epochMillis": 1446768574275,
"friendly": "06/Nov/15 11:09 AM",
"iso8601": "2015-11-06T11:09:34+1100"
}
},
{
"status": "Waiting for Support",
"statusDate": {
"epochMillis": 1446768162074,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:42+1100"
}
},
{
"status": "Waiting for Customer",
"statusDate": {
"epochMillis": 1446768124625,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:04+1100"
}
}
]
}
Обратите внимание, что это публичные статусы, которые может видеть клиент. Возможно иметь внутренние статусы, которые могут помочь сервисной команде управлять своей работой (например, «Обзор»), но не нужно делиться с клиентами.
Чтобы увидеть переходы состояния, которые возможны для этой задачи, вы можете использовать API REST платформы JIRA, как показано ниже:
Пример запроса J
curl -H "X-ExperimentalApi: true" -u agent:agent -X GET "http://localhost:2990/jira/rest/api/2/issue/17227/transitions" | python -mjson.tool
Ответ
{
"expand": "transitions",
"transitions": [
{
"id": "801",
"name": "Resolve this issue",
"to": {
"description": "A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.",
"iconUrl": "http://localhost:2990/jira/images/icons/statuses/resolved.png",
"id": "5",
"name": "Resolved",
"self": "http://localhost:2990/jira/rest/api/2/status/5",
"statusCategory": {
"colorName": "green",
"id": 3,
"key": "done",
"name": "Done",
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/3"
}
}
},
{
"id": "851",
"name": "Respond to customer",
"to": {
"description": "This was auto-generated by JIRA Service Desk during workflow import",
"iconUrl": "http://localhost:2990/jira/images/icons/statuses/generic.png",
"id": "10022",
"name": "Waiting for Customer",
"self": "http://localhost:2990/jira/rest/api/2/status/10022",
"statusCategory": {
"colorName": "yellow",
"id": 4,
"key": "indeterminate",
"name": "In Progress",
"self": "http://localhost:2990/jira/rest/api/2/statuscategory/4"
}
}
}
]
}
Соглашения о Сервисном обслуживании Запроса
Соглашения о Сервисном обслуживании Запроса (SLAs) используются, чтобы отследить, сколько времени проведено, обслуживая запросы клиента. Таймеры установлены, когда Запросы входят в определенные условия. Времена цели могут быть определены как идеальное время, чтобы сделать работу прежде, чем это будут считать нарушением обслуживания. Например, Вы можете стремиться возвращаться клиенту в течение четырех часов, и следовательно можете иметь “Время к первому ответу” определенный SLA.
Информация SLA не отображается клиентам. Она используется, чтобы помочь сервисной команде узнать, что является самой важной задачей, на которую они должны обратить внимание.
Показатели SLA могут запускаться и останавливаться в течение срока службы запроса. Например, у вас может быть определено «Время ожидания поддержки», когда таймеры работают только в то время, когда они находятся в командных группах службы поддержки. Таким образом, SLA может иметь много повторяющихся «циклов» и возможный «текущий цикл». Каждый цикл, возможно, был завершен в течение целевого времени или может быть «нарушен».
Достаточно теории, давайте посмотрим, как это выглядит! Следующий вызов API REST возвращает информацию SLA для конкретного запроса:
Пример запроса K
url -H "X-ExperimentalApi: true" -u agent:agent -X GET "http://localhost:2990/jira/rest/servicedeskapi/request/17227/sla" | python -mjson.tool
Ответ
{
"_links": {
"base": "http://localhost:2990/jira",
"context": "/jira",
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/sla"
},
"isLastPage": true,
"limit": 50,
"size": 2,
"start": 0,
"values": [
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/sla/30"
},
"completedCycles": [],
"id": 30,
"name": "Time to resolution",
"ongoingCycle": {
"breachTime": {
"epochMillis": 1446789600000,
"friendly": "06/Nov/15 5:00 PM",
"iso8601": "2015-11-06T17:00:00+1100"
},
"breached": true,
"elapsedTime": {
"friendly": "136h 18m",
"millis": 490682163
},
"goalDuration": {
"friendly": "4h",
"millis": 14400000
},
"paused": false,
"remainingTime": {
"friendly": "-132h 18m",
"millis": -476282163
},
"startTime": {
"epochMillis": 1446768040477,
"friendly": "06/Nov/15 11:00 AM",
"iso8601": "2015-11-06T11:00:40+1100"
},
"withinCalendarHours": true
}
},
{
"_links": {
"self": "http://localhost:2990/jira/rest/servicedeskapi/request/17227/sla/43"
},
"completedCycles": [
{
"breached": false,
"elapsedTime": {
"friendly": "0m",
"millis": 0
},
"goalDuration": {
"friendly": "15m",
"millis": 900000
},
"remainingTime": {
"friendly": "15m",
"millis": 900000
},
"startTime": {
"epochMillis": 1446768040477,
"friendly": "06/Nov/15 11:00 AM",
"iso8601": "2015-11-06T11:00:40+1100"
},
"stopTime": {
"epochMillis": 1446768124651,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:04+1100"
}
},
{
"breached": false,
"elapsedTime": {
"friendly": "0m",
"millis": 0
},
"goalDuration": {
"friendly": "15m",
"millis": 900000
},
"remainingTime": {
"friendly": "15m",
"millis": 900000
},
"startTime": {
"epochMillis": 1446768162075,
"friendly": "06/Nov/15 11:02 AM",
"iso8601": "2015-11-06T11:02:42+1100"
},
"stopTime": {
"epochMillis": 1446768574276,
"friendly": "06/Nov/15 11:09 AM",
"iso8601": "2015-11-06T11:09:34+1100"
}
}
],
"id": 43,
"name": "Time waiting for support",
"ongoingCycle": {
"breachTime": {
"epochMillis": 1446776100000,
"friendly": "06/Nov/15 1:15 PM",
"iso8601": "2015-11-06T13:15:00+1100"
},
"breached": true,
"elapsedTime": {
"friendly": "136h 18m",
"millis": 490682163
},
"goalDuration": {
"friendly": "15m",
"millis": 900000
},
"paused": false,
"remainingTime": {
"friendly": "-136h 3m",
"millis": -489782163
},
"startTime": {
"epochMillis": 1446768682500,
"friendly": "06/Nov/15 11:11 AM",
"iso8601": "2015-11-06T11:11:22+1100"
},
"withinCalendarHours": true
}
}
]
}
Поздравляем! Вы завершили этот обзор модели домена JIRA Service Desk. Есть шоколад! Теперь вы должны хорошо понять, как работают объекты. Затем ознакомьтесь с документацией API REST API JIRA Service Desk и попробуйте сами ее использовать.
По материалам Atlassian JIRA Server Developer Exploring the JIRA Service Desk domain model via the REST APIs
Как написать простой веб-сервис с помощью Django REST
Часто при создании веб-проектов мы используем фреймворк Django, и сегодня я расскажу почему. Экономя время занятым читателям, скажу сразу и в двух словах: простота, скорость (создания веб-приложений). А для тех, кому интересна техническая сторона: что, для чего и как — я распишу шаги создания нехитрого веб-сервиса.
Что такое Django?
Django — это высокоуровневый веб-фреймворк для языка Python, позволяющий быстро разрабатывать динамические веб-приложения.
Изначально Django был разработан для написания новостных сайтов, поэтому основным требованием было решение двух проблем:
- регулярное интенсивное наполнение сайта материалом по требованию редакции;
- соответствие высоким стандартам качества сайта.
В результате у нас есть удобный фреймворк, который существенно ускоряет процесс разработки и дает возможность разделить процессы программирования, верстки и дизайна. По сути, Django можно назвать каркасом веб-приложений.
Одним из основных принципов Django является DRY (Don’t Repeat Yourself), что в переводе с английского означает «Не повторяйся», который нацелен на устранение повторений в коде.
Для чего нужен Django REST Framework?
Как понятно из названия, Django REST Framework — это лёгкий фреймворк для Django, поддерживающий идеологию REST (Representational State Transfer) — репрезентативную передачу состояния. Использование этого фреймворка позволяет легко стандартизировать запросы к базе данных и одновременно создавать RESTful WEB API нашего сайта.
Особенности:
- Отображение ресурсов с использованием новой функции Django — Class Based Views.
- Поддержка ModelResources и проверка входных данных.
- Наличие подключаемых парсеров, отображений, авторизации и прав доступа — все легко настраивается.
- Указание типа материала с использованием Access в заголовках HTTP-запросов.
- Поддержка форм с возможностью проверки.
Итак, переходим к созданию простейшего приложения для демонстрации скорости разработки с использованием Django REST Framework.
Установку и настройку Python, Django я пропускаю, так как по этому поводу в Интернете материала очень много. Для начала нам необходимо создать проект. Делается это командой
django-admin.py startproject blogpost
Имя нашего проекта будет BlogPost. Команда автоматически создаст каталог проекта и некоторые необходимые нам файлы по умолчанию. Далее нам необходимо создать модели наших таблиц в базе данных. Для этого редактируем файл models.py:
from django.db import models class BlogPost(models.Model): title = models.CharField(max_length=128) content = models.TextField() created = models.DateTimeField(auto_now_add=True) class Comment(models.Model): blogpost = models.ForeignKey(BlogPost, editable=False, related_name='comments') comment = models.TextField() created = models.DateTimeField(auto_now_add=True)
Мы создали две таблицы BlogPost и Comment. На самом деле в базе данных они буду именованы не так, но мы работает только с ORM, поэтому нам об этом заботится не надо. Далее создадим файл ресурсов resource.py содержащий следующее:
from django.core.urlresolvers import reverse from djangorestframework.resources import ModelResource from blogpost.models import BlogPost, Comment class BlogPostResource(ModelResource): model = BlogPost fields = ('created', 'title', 'content', 'url', 'comments',) ordering = ('-created',) def comments(self, instance): return reverse('comments', kwargs={'blogpost':instance.id}) class CommentResource(ModelResource): model = Comment fields = ('created', 'comment', 'url', 'blogpost',) ordering = ('-created',) def blogpost(self, instance): return reverse('blog-post', kwargs={'id':instance./]+)/$', InstanceModelView.as_view(resource=CommentResource)), )
Представления имеют говорящие названия. Теперь в файле settings.py добавим описание базы данных:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'NAME': 'database.sqlite3', # Or path to database file if using sqlite3. 'USER': '', # Not used with sqlite3. 'PASSWORD': '', # Not used with sqlite3. 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 'PORT': '', # Set to empty string for default. Not used with sqlite3. } }
Для упрощения используем sqlite3. Список приложений (settings.py) необходимо привести к следующему виду:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'djangorestframework', 'blogpost', # Uncomment the next line to enable the admin: # 'django.contrib.admin', # Uncomment the next line to enable admin documentation: # 'django.contrib.admindocs', )
Тем самым мы описали, что наше приложение BlogPost включено в проект, а приложение djangorestframework нам необходимо для того, что бы django смог подключить тестовые шаблоны для вывода данных. Запускаем следующую команду:
python manage.py syncdb
Эта команда создаст базу данных и необходимые в ней таблицы, после этого можно запускать проект и прямо с браузера тестировать серверное API:
python manage.py runserver 0.0.0.0:8000
Каким же функционалом обладает наш сервис?
- При вызове GET http://localhost:8000 запроса нам возвращается список постов, если они есть.
- При вызове POST http://localhost:8000 и отправке данных, таких как title и content, мы создаем новые посты.
- Если у нас уже существует пост, например id = 3, то при вызове GET http://localhost:8000/comments нам вернется список комментариев к этому посту.
- Отправка POST http://localhost:8000/3/comments с необходимыми данными создаст новый комментарий.
- Также можно вызывать OPTIONS http://localhost:8000/3/comments, OPTIONS http://localhost:8000/, который вернет формат данных.
- Что бы изменить какой-то пост, например id = 5, мы отправляем PUT http://localhost:8000/5/ с необходимыми данными, то же самое можно делать с комментариями.
- Всё это можно тестировать при помощи браузера, так как браузер передает в заголовке Accept (html/text) и фреймворк автоматически использует тестовые шаблоны для отображения и управления данными.
Про Django можно рассказывать много и долго, моей же целью было продемонстрировать, насколько он удобный и практичный. Если он вас тоже заинтересовал, у проекта есть замечательный сайт с английской документацией. Успешных вам проектов!
Информация о документе Предисловие Часть I Введение 1. Обзор 2. Использование учебных примеров Часть II Веб-уровень 3. Начало работы с веб-приложениями 4. Технология JavaServer Faces 5. Знакомство с Facelets 6. Язык выражений 7. Использование технологии JavaServer Faces на веб-страницах 8.Использование конвертеров, слушателей и валидаторов 9. Разработка с использованием технологии JavaServer Faces 10. Технология JavaServer Faces: расширенные концепции 11. Использование Ajax с технологией JavaServer Faces 12. Составные компоненты: дополнительные темы и пример 13. Создание настраиваемых компонентов пользовательского интерфейса и других настраиваемых объектов 14. Настройка приложений JavaServer Faces 15. Технология сервлетов Java 16.Загрузка файлов с помощью технологии сервлетов Java 17. Интернационализация и локализация веб-приложений Веб-службы, часть III 18. Введение в веб-службы 19. Создание веб-сервисов с помощью JAX-WS 20. Создание веб-служб RESTful с помощью JAX-RS Создание класса корневых ресурсов RESTful Разработка веб-служб RESTful с помощью JAX-RS Обзор приложения JAX-RS Шаблоны аннотации @Path и пути URI Ответы на методы и запросы HTTP Аннотации указателя метода запроса Использование поставщиков сущностей для сопоставления тел сущностей HTTP-ответа и запроса Использование @Consumes и @Produces для настройки запросов и ответов Аннотация @Produces Аннотация @Consumes Параметры запроса на извлечение Примеры приложений для JAX-RS Веб-служба RESTful Создание веб-службы RESTful с помощью IDE NetBeans Пример приложения rsvp Компоненты примера приложения rsvp Запуск примера приложения rsvp Примеры из реальной жизни Дополнительная информация о JAX-RS 21.JAX-RS: дополнительные темы и пример Корпоративные бобы, часть IV 22. Корпоративные бобы 23. Начало работы с корпоративными компонентами 24. Запуск примеров корпоративных компонентов 25. Пример объекта, управляемого сообщениями 26. Использование встроенного контейнера корпоративных компонентов 27. Использование асинхронного вызова метода в сессионных компонентах Часть V Внедрение контекстов и зависимостей для платформы Java EE 28.Введение в внедрение контекстов и зависимостей для платформы Java EE 29. Запуск основных контекстов и примеров внедрения зависимостей 30. Внедрение контекстов и зависимостей для платформы Java EE: дополнительные темы 31. Выполнение расширенных примеров внедрения контекстов и зависимостей Часть VI Стойкость 32. Введение в Java Persistence API 33. Запуск примеров сохранения состояния 34. Язык запросов сохраняемости Java 35.Использование API критериев для создания запросов 36. Создание и использование запросов на основе строковых критериев 37. Управление одновременным доступом к данным объекта с блокировкой 38. Использование кэша второго уровня с приложениями Java Persistence API Часть VII Безопасность 39. Введение в безопасность на платформе Java EE 40. Начало работы Защита веб-приложений 41. Начало работы Защита корпоративных приложений 42.Безопасность Java EE: дополнительные темы Часть VIII Технологии поддержки Java EE 43. Введение в технологии поддержки Java EE 44. Сделки 45. Ресурсы и адаптеры ресурсов 46. Пример адаптера ресурсов 47. Концепции службы сообщений Java 48. Примеры службы сообщений Java 49. Проверка компонентов: расширенные темы 50. Использование перехватчиков Java EE Часть IX Примеры из практики 51.Пример книжного магазина Duke’s Bookstore 52. Пример из практики «Репетиторство Герцога» 53. Пример из практики Duke’s Forest Индекс | Что такое веб-службы RESTful? Веб-службы RESTful созданы для лучшей работы в Интернете. Изобразительное State Transfer Следующие принципы способствуют тому, чтобы приложения RESTful были простыми, легкими и быстрыми:
Авторские права © 2013, Oracle и / или ее дочерние компании. Все права защищены. Юридические уведомления |
Что такое ОТДЫХ? | Codecademy
RE Перенос состояния презентации
REST, или REpresentational State Transfer, представляет собой архитектурный стиль для обеспечения стандартов между компьютерными системами в Интернете, что упрощает взаимодействие систем друг с другом.REST-совместимые системы, часто называемые системами RESTful, характеризуются тем, что они не имеют состояния и разделяют проблемы клиента и сервера. Мы рассмотрим, что означают эти термины и почему они являются полезными характеристиками сервисов в Интернете.
Разделение клиента и сервера
В архитектурном стиле REST реализация клиента и реализация сервера могут выполняться независимо друг от друга, не зная друг о друге. Это означает, что код на стороне клиента можно изменить в любое время, не влияя на работу сервера, а код на стороне сервера можно изменить, не влияя на работу клиента.
До тех пор, пока каждая сторона знает, какой формат сообщений отправлять другой, они могут быть модульными и отдельными. Отделив проблемы пользовательского интерфейса от проблем хранения данных, мы улучшаем гибкость интерфейса для разных платформ и улучшаем масштабируемость за счет упрощения серверных компонентов. Кроме того, разделение позволяет каждому компоненту развиваться независимо.
Используя интерфейс REST, разные клиенты обращаются к одним и тем же конечным точкам REST, выполняют одни и те же действия и получают одинаковые ответы.
Безгражданство
Системы, которые следуют парадигме REST, не имеют состояния, что означает, что серверу не нужно ничего знать о том, в каком состоянии находится клиент, и наоборот. Таким образом, и сервер, и клиент могут понимать любое полученное сообщение, даже не просматривая предыдущие сообщения. Это ограничение безгражданства обеспечивается за счет использования ресурсов , а не команд . Ресурсы — это существительные в сети: они описывают любой объект, документ или предмет, который вам может понадобиться сохранить или отправить в другие службы.
Поскольку системы REST взаимодействуют посредством стандартных операций с ресурсами, они не полагаются на реализацию интерфейсов.
Эти ограничения помогают приложениям RESTful достичь надежности, быстрой производительности и масштабируемости как компонентов, которыми можно управлять, обновлять и повторно использовать, не затрагивая систему в целом, даже во время работы системы.
Теперь мы рассмотрим, как на самом деле происходит взаимодействие между клиентом и сервером, когда мы реализуем интерфейс RESTful.
Обмен данными между клиентом и сервером
В архитектуре REST клиенты отправляют запросы на получение или изменение ресурсов, а серверы отправляют ответы на эти запросы. Давайте рассмотрим стандартные способы отправки запросов и ответов.
Создание запросов
REST требует, чтобы клиент сделал запрос к серверу, чтобы получить или изменить данные на сервере. Запрос обычно состоит из:
- HTTP-глагол, который определяет, какую операцию выполнять
- заголовок , который позволяет клиенту передавать информацию о запросе
- путь к ресурсу
- необязательное тело сообщения, содержащее данные
HTTP-глаголы
Есть 4 основных HTTP-глагола, которые мы используем в запросах для взаимодействия с ресурсами в системе REST:
- GET — получить определенный ресурс (по идентификатору) или коллекцию ресурсов
- POST — создать новый ресурс
- PUT — обновить конкретный ресурс (по id)
- DELETE — удалить определенный ресурс по идентификатору
Вы можете узнать больше об этих HTTP-глаголах в следующей статье Codecademy:
Заголовки и параметры принятия
В заголовке запроса клиент отправляет контент, который он может получить от сервера.Это называется полем Accept
, и оно гарантирует, что сервер не отправляет данные, которые не могут быть поняты или обработаны клиентом. Варианты типов контента — это типы MIME (или многоцелевые расширения почты Интернета, о которых вы можете узнать больше в MDN Web Docs.
Типы
MIME, используемые для указания типов содержимого в поле Accept
, состоят из типа
и подтипа
. Они разделены косой чертой (/).
Например, текстовый файл, содержащий HTML, будет указан с типом text / html
.Если бы этот текстовый файл содержал вместо этого CSS, он был бы указан как text / css
. Общий текстовый файл будет обозначен как text / plain
. Однако это значение по умолчанию, text / plain
, не является универсальным. Если клиент ожидает text / css
и получает text / plain
, он не сможет распознать содержимое.
Другие типы и часто используемые подтипы:
-
изображение
—изображение / png
,изображение / jpeg
,изображение / gif
-
аудио
—аудио / wav
,аудио / MPEG
-
видео
—видео / mp4
,видео / ogg
-
приложение
—приложение / json
,приложение / pdf
,приложение / xml
,приложение / поток октетов
Например, клиент, обращающийся к ресурсу с идентификатором ,
23 в ресурсе статей
на сервере, может отправить запрос GET следующим образом:
GET / статьи / 23 Accept: text / html, application / xhtml
Поле заголовка
Accept
в этом случае говорит, что клиент примет содержимое вtext / html
илиapplication / xhtml
.Пути
Запросы должны содержать путь к ресурсу, над которым должна выполняться операция. В RESTful API пути должны быть спроектированы так, чтобы помочь клиенту знать, что происходит.
Обычно первая часть пути должна иметь форму множественного числа ресурса. Это упрощает чтение и понимание вложенных путей.
Путь вроде
fashionboutique.com/customers/223/orders/12
ясен в том, на что он указывает, даже если вы никогда раньше не видели этот конкретный путь, потому что он иерархический и описательный.Мы видим, что мы обращаемся к заказу с идентификатором12 для клиента с идентификатором
223.
Пути должны содержать информацию, необходимую для поиска ресурса с необходимой степенью специфичности. При обращении к списку или набору ресурсов не всегда необходимо добавлять идентификатор
, идентификатор
. Например, POST-запрос на путьfashionboutique.com/customers
не требует дополнительного идентификатора, поскольку сервер сгенерируетid
для нового объекта.Если мы пытаемся получить доступ к одному ресурсу, нам нужно добавить к пути идентификатор
, идентификатор
.
Например:
GET fashionboutique.com/customers/:id
— извлекает товар из ресурсаcustomers
с указанным идентификаторомid
.
DELETE fashionboutique.com/customers/:id
— удаляет товар из ресурсаcustomers
с указанным идентификаторомid
.Отправка ответов
Типы содержимого
В случаях, когда сервер отправляет полезные данные клиенту, сервер должен включать в заголовок ответа
типа содержимого
.Это поле заголовка типа содержимого предупреждает клиента о типе данных, которые он отправляет в теле ответа. Эти типы контента являются типами MIME, как и в полеaccept
заголовка запроса. Тип содержимого, который сервер отправляет обратно в ответе, должен быть одной из опций, которые клиент указал в поле
accept
запроса.Например, когда клиент обращается к ресурсу с идентификатором
23 в ресурсе
статей
с этим запросом GET:
GET / article / 23 HTTP / 1.1 Принять: text / html, application / xhtml
Сервер может отправить обратно контент с заголовком ответа:
HTTP / 1.1 200 (ОК) Content-Type: text / html
Это будет означать, что запрошенное содержимое возвращается в теле ответа с типом содержимого
из
text / html
, который, по словам клиента, он сможет принять. .Коды ответа
Ответы от сервера содержат коды состояния, предупреждающие клиента об успешном завершении операции.Как разработчику вам не нужно знать все коды статуса (их много), но вы должны знать наиболее распространенные и способы их использования:
Код состояния | Значение |
---|---|
200 (ОК) | Это стандартный ответ для успешных HTTP-запросов. |
201 (СОЗДАНО) | Это стандартный ответ на HTTP-запрос, в результате которого элемент был успешно создан. |
204 (БЕЗ СОДЕРЖАНИЯ) | Это стандартный ответ для успешных HTTP-запросов, когда в теле ответа ничего не возвращается. |
400 (ПЛОХОЙ ЗАПРОС) | Запрос не может быть обработан из-за неправильного синтаксиса запроса, чрезмерного размера или другой ошибки клиента. |
403 (ЗАПРЕЩЕНО) | У клиента нет разрешения на доступ к этому ресурсу. |
404 (НЕ НАЙДЕН) | В данный момент ресурс не может быть найден.Возможно, он был удален или еще не существует. |
500 (ОШИБКА ВНУТРЕННЕГО СЕРВЕРА) | Общий ответ на непредвиденный сбой, если нет более конкретной информации. |
Для каждого HTTP-глагола есть ожидаемые коды состояния, которые сервер должен вернуть в случае успеха:
- GET — возврат 200 (ОК)
- POST — возврат 201 (СОЗДАНО)
- PUT — возврат 200 (ОК)
- DELETE — возврат 204 (NO CONTENT)
Если операция завершилась неудачно, верните наиболее конкретный возможный код состояния, соответствующий обнаруженной проблеме.
Примеры запросов и ответов
Допустим, у нас есть приложение, которое позволяет просматривать, создавать, редактировать и удалять клиентов и заказы для небольшого магазина одежды, расположенного по адресу fashionboutique.com
. Мы могли бы создать HTTP API, который позволяет клиенту выполнять следующие функции:
Если бы мы хотели просмотреть всех клиентов, запрос выглядел бы так:
ПОЛУЧИТЬ http://fashionboutique.com/customers Принять: application / json
Возможный заголовок ответа будет выглядеть так:
Код состояния: 200 (ОК) Тип содержимого: application / json
, за которым следуют данные
клиентов
, запрошенные в форматеapplication / json
.Создайте нового клиента, разместив данные:
ЗАПИСЬ http://fashionboutique.com/customers Тело: { "покупатель": { «Name» = «Сцилла Бусс», «Email» = «[электронная почта защищена]» } }
Затем сервер генерирует
id
для этого объекта и возвращает его клиенту с таким заголовком, как:
201 (СОЗДАНО) Content-type: application / json
Для просмотра отдельного клиента мы ПОЛУЧИМ , указав идентификатор этого клиента:
ПОЛУЧИТЬ http: // fashionboutique.ru / customers / 123 Принять: application / json
Возможный заголовок ответа будет выглядеть так:
Код состояния: 200 (ОК) Content-type: application / json
, за которым следуют данные для ресурса
customer
с идентификатором23 в формате
application / json
.Мы можем обновить этого клиента, введя PUT , указав новые данные:
РАЗМЕСТИТЬ http: // fashionboutique.ru / customers / 123 Тело: { "покупатель": { «Name» = «Сцилла Бусс», «Email» = «[электронная почта защищена]» } }
Возможный заголовок ответа должен иметь код состояния
: 200 (OK)
, чтобы уведомить клиента о том, что элемент с идентификатором123 был изменен.
Мы также можем УДАЛИТЬ этого клиента, указав его идентификатор
:
УДАЛИТЬ http://fashionboutique.com/customers/123
Ответ будет иметь заголовок, содержащий код состояния
: 204 (БЕЗ КОНТЕНТА)
, уведомляющий клиента о том, что элемент с идентификатором123 было удалено, а в теле ничего нет.
Практика с REST
Давайте представим, что мы создаем сайт для сбора фотографий. Мы хотим создать API, чтобы отслеживать пользователей, места проведения и фотографии этих мест. Этот сайт имеет
index.html
иstyle.css
. У каждого пользователя есть имя пользователя и пароль. У каждой фотографии есть место проведения и владелец (то есть пользователь, который сделал снимок). У каждого места есть название и адрес.
Можете ли вы разработать систему REST, которая вмещала бы:
- хранение пользователей, фотографий и мест проведения
- доступ к местам проведения и доступ к определенным фотографиям определенного места
Начните с написания:
- какие запросы мы хотели бы отправлять
- какие ответы должен вернуть сервер
- какой тип содержимого
Возможное решение — модели
{ "Пользователь": { "id": <Целое число>, «Имя пользователя»:
, «Пароль»: } }
{ "Фото": { "id": <Целое число>, «Location_id»: <Целое число>, «Author_id»: <Целое число> } }
{ "место проведения": { "id": <Целое число>, «Имя»:
, «Адрес»: } } Возможное решение — запросы / ответы
Запросы GET
Запрос-
GET / index.HTML
Принять:текст / html
Ответ-
200 (ОК)
Тип содержимого:текст / html
Запрос-
GET /style.css
Принять: текст/ css
Ответ-
200 (ОК)
Тип содержимого:текст / css
Запрос-
GET / площадки
Принять: приложение/ json
Ответ-
200 (ОК)
Тип содержимого:приложение / json
Запрос-
GET / Venues /: id
Принять: приложение/ json
Ответ-
200 (ОК)
Тип содержимого:приложение / json
Запрос-
GET / Venues /: id / photos /: id
Принять: приложение/ json
Ответ-
200 (ОК)
Content-type:image / png
POST-запросы
Запрос-
POST / пользователей
Ответ-
201 (СОЗДАН)
Тип содержимого:приложение / json
Запрос-
POST / места
Ответ-
201 (СОЗДАН)
Тип содержимого:приложение / json
Запрос-
POST / Venues /: id / photos
Ответ-
201 (СОЗДАН)
Тип содержимого:приложение / json
Запросы PUT
Запрос-
PUT / users /: id
Ответ-
200 (ОК)Запрос-
PUT / места /: id
Ответ-
200 (ОК)Запрос-
PUT / Venues /: id / photos /: id
Ответ-
200 (ОК)Запросы DELETE
Запрос-
УДАЛИТЬ / места /: id
Ответ-
204 (БЕЗ СОДЕРЖАНИЯ)Запрос-
УДАЛИТЬ / места /: id / photos /: id
Ответ-
204 (БЕЗ СОДЕРЖАНИЯ)Image Service — ArcGIS REST API | ArcGIS for Developers
{ "currentVersion": 10.3, "serviceDescription": "Описание службы тестового изображения", "name": "wsiearth.tif", "описание": "wsiearth.tif", "степень": { «xmin»: -180, «ymin»: -90, «xmax»: 180, «ymax»: 90, "SpaceReference": { "wkid": 4326, "latestWkid": 4326 } }, "initialExtent": { «xmin»: -180, «ymin»: -90, «xmax»: 180, «ymax»: 90, "SpaceReference": { "wkid": 4326, "latestWkid": 4326 } }, "полностью": { «xmin»: -180, «ymin»: -90, «xmax»: 180, «ymax»: 90, "SpaceReference": { "wkid": 4326, "latestWkid": 4326 } }, "timeInfo": { "startTimeField": "AcquisitionDate", "endTimeField": "", "timeExtent": [ 1106822673000, г. 1125
1000 ], "timeReference": нуль }, «pixelSizeX»: 30.386, г. "pixelSizeY": 30,386, "bandCount": 3, "pixelType": "U8", «minPixelSize»: 0,0, «maxPixelSize»: 0,0, "copyrightText": "ESRI", "editFieldsInfo": { "creationDateField": "DateCreated", "creatorField": "CreationUser", "editDateField": "DateModified", "editorField": "LastUser", "область": "мойсервер" }, "ownerBasedAccessControlForRasters": { "allowOthersToUpdate": false, "allowOthersToDelete": false }, "serviceDataType": "esriImageServiceDataTypeRGB", "minValues": [ 0.0, 0,0, 0,0 ], "maxValues": [ 255,0, 254,0, 255,0 ], "значения величин" : [ 82,707, 107,448, 60,118 ], "stdvValues": [ 39,838, 37,735, 36,466 ], "objectIdField": "OBJECTID", "поля": [ { "name": "OBJECTID", "тип": "esriFieldTypeOID", "псевдоним": "OBJECTID", "домен": нуль, "editable": false, "обнуляемый": ложь }, { "name": "Форма", "тип": "esriFieldTypeGeometry", "псевдоним": "Форма", "домен": нуль, "editable": false, "обнуляемый": ложь }, { "name": "Имя", "тип": "esriFieldTypeString", "Псевдоним", "домен": нуль, "editable": правда, "обнуляемый": истина, «длина»: 50 }, { "name": "Категория", "тип": "esriFieldTypeInteger", "псевдоним": "Категория", "домен": { "тип": "codedValue", "name": "MosaicCatalogItemCategoryDomain", "codedValues": [ { "name": "Неизвестно", «код»: 0 }, { "name": "Основной", «код»: 1 }, { "name": "Обзор", «код»: 2 }, { "name": "Необработанный обзор", «код»: 3 }, { "name": "Частичный обзор", «код»: 4 }, { "name": "Загружено", «код»: 253 }, { "name": "Неполное", «код»: 254 }, { "name": "Пользовательский", «код»: 255 } ] }, "editable": false, "обнуляемый": истина } ], "возможности": "Изображение, метаданные, пиксели, каталог, загрузка", "defaultMosaicMethod": "Центр", "allowedMosaicMethods": "Центр, Северо-Запад, LockRaster, По атрибуту, Надир, Точка обзора, Линия стыка", "maxRecordCount": 500, "maxImageHeight": 4100, "maxImageWidth": 15000, "defaultResamplingMethod": "Билинейный", "maxDownloadImageCount": 20, «maxDownloadSizeLimit»: 2048, "maxMosaicImageCount": 20, "singleFusedMapCache": истина, "tileInfo": { «строк»: 256, «cols»: 256, «dpi»: 96, "формат": "Смешанный", «Качество сжатия»: 75, "источник": { «х»: -5120900, «y»: 9998100 }, "пространственная ссылка": {"wkt": "PROJCS [\" WGS_84_UTM_zone_12N \ ", GEOGCS [\" GCS_WGS_1984 \ ", DATUM [\" D_WGS_1984 \ », SPHEROID [\" WGS_1984 \ ", 6378137.0,298.257223563]], ПРИЕМ [\ "Гринвич \", 0,0], ЕДИНИЦА [\ "Градус \", 0,0174532925199433]], ПРОЕКЦИЯ [\ "Поперечный_ меркатор \"], ПАРАМЕТР [\ "ложный_вкус \", 500000,0], ПАРАМЕТР [\ "false_northing \", 0,0], ПАРАМЕТР [\ "центральный_меридиан \", - 111,0], ПАРАМЕТР [\ "коэффициент_масштабности \", 0,9996], ПАРАМЕТР [\ "широта_начина \", 0,0], ЕДИНИЦА [\ "метр \", 1.0]] "}, "lods": [ { «уровень»: 0, «разрешение»: 529.1677250021168, «масштаб»: 2000000 }, { "1-й уровень, «разрешение»: 264.5838625010584, г. «масштаб»: 1000000 }, { "уровень 2, «разрешение»: 132.2919312505292, «масштаб»: 500000 }, { "Уровень 3, «разрешение»: 66.1459656252646, «масштаб»: 250000 }, { «уровень»: 4, «разрешение»: 33.0729828126323, «масштаб»: 125000 } ] }, "allowRasterFunction": true, "rasterFunctionInfos": [ { "name": "NDVIWithColormap", "description": "Шаблон растровой функции.", "помощь": "" } ], "rasterTypeInfos": [ { "name": "Набор растровых данных", "description": "Поддерживает все наборы растровых данных ArcGIS", "помощь": "" } ], "mensurationCapabilities": "Базовая, высота основания до верха", "hasHistograms": верно, "hasColormap": ложь, "hasRasterAttributeTable": ложь, "hasMultidimensions": правда, "allowComputeTiePoints": false, "useStandardizedQueries": true, "supportsStatistics": верно, "supportsAdvancedQueries": true, "SpaceReference": { "wkid": 4326, "latestWkid": 4326 }, "advancedQueryCapabilities": { "useStandardizedQueries": true, "supportsStatistics": верно, "supportsOrderBy": правда, "supportsDistinct": правда, "supportsPagination": true } }Что такое дизайн REST API?
Дизайн REST или RESTful API (передача репрезентативного состояния) предназначен для использования преимуществ существующих протоколов.Хотя REST можно использовать практически с любым протоколом, он обычно использует преимущества HTTP при использовании для веб-API. Это означает, что разработчикам не нужно устанавливать библиотеки или дополнительное программное обеспечение, чтобы воспользоваться преимуществами дизайна REST API. Дизайн REST API был определен доктором Роем Филдингом в его докторской диссертации 2000 года. Он отличается невероятной гибкостью. Поскольку данные не привязаны к методам и ресурсам, REST может обрабатывать несколько типов вызовов, возвращать разные форматы данных и даже структурно изменяться при правильной реализации гипермедиа.
Эта свобода и гибкость, присущие дизайну REST API, позволяют создавать API, который отвечает вашим потребностям, а также отвечает потребностям самых разных клиентов. В отличие от SOAP, REST не ограничивается XML, но вместо этого может возвращать XML, JSON, YAML или любой другой формат в зависимости от того, что запрашивает клиент. И, в отличие от RPC, пользователям не требуется знать имена процедур или конкретные параметры в определенном порядке.
Однако у REST API есть недостатки. Вы можете потерять возможность поддерживать состояние в REST, например, внутри сеансов, и новым разработчикам может быть сложнее использовать его.Также важно понять, что делает REST API RESTful и почему существуют эти ограничения, прежде чем создавать свой API. В конце концов, если вы не понимаете, почему что-то спроектировано таким образом, вы можете препятствовать своим усилиям, даже не осознавая этого.
Понимание дизайна REST API
Хотя большинство API-интерфейсов утверждают, что они являются RESTful, они не соответствуют требованиям и ограничениям, заявленным доктором Филдингом. При разработке REST API необходимо учитывать шесть ключевых ограничений при принятии решения о том, подходит ли этот тип API для вашего проекта.
Клиент-сервер
Ограничение клиент-сервер основывается на концепции, согласно которой клиент и сервер должны быть отделены друг от друга и могут развиваться индивидуально и независимо. Другими словами, я должен иметь возможность вносить изменения в свое мобильное приложение, не влияя ни на структуру данных, ни на структуру базы данных на сервере. В то же время я должен иметь возможность изменять базу данных или вносить изменения в свое серверное приложение, не влияя на мобильный клиент.Это создает разделение задач, позволяя каждому приложению расти и масштабироваться независимо от другого и позволяя вашей организации расти быстро и эффективно.
Без сохранения состояния
API-интерфейсы REST не имеют состояния, что означает, что вызовы могут выполняться независимо друг от друга, и каждый вызов содержит все данные, необходимые для успешного завершения. REST API не должен полагаться на данные, хранящиеся на сервере или в сеансах, чтобы определять, что делать с вызовом, а полагаться исключительно на данные, которые предоставляются в самом вызове.Идентификационная информация не сохраняется на сервере при совершении звонков. Вместо этого каждый вызов сам по себе содержит необходимые данные, такие как ключ API, токен доступа, идентификатор пользователя и т. Д. Это также помогает повысить надежность API за счет наличия всех данных, необходимых для выполнения вызова, вместо того, чтобы полагаться на серию вызовов с состоянием сервера для создания объекта, что может привести к частичному отказу. Вместо этого, чтобы снизить требования к памяти и сохранить как можно более масштабируемое приложение, RESTful API требует, чтобы любое состояние сохранялось на клиенте, а не на сервере.
Кэш
Поскольку API без сохранения состояния может увеличить накладные расходы на запросы, обрабатывая большие нагрузки входящих и исходящих вызовов, REST API должен быть разработан таким образом, чтобы способствовать хранению кэшируемых данных. Это означает, что, когда данные являются кэшируемыми, ответ должен указывать, что данные могут храниться до определенного времени (истекает), или в случаях, когда данные должны быть в реальном времени, ответ не должен кэшироваться клиент. Включив это критическое ограничение, вы не только значительно сократите количество взаимодействий с вашим API, сократив использование внутреннего сервера, но также предоставите своим пользователям API инструменты, необходимые для предоставления максимально быстрых и эффективных приложений.Имейте в виду, что кеширование выполняется на стороне клиента. Хотя вы можете кэшировать некоторые данные в своей архитектуре для обеспечения общей производительности, цель состоит в том, чтобы проинструктировать клиента о том, как он должен действовать, и может ли клиент временно хранить данные.
Унифицированный интерфейс
Ключом к отделению клиента от сервера является наличие унифицированного интерфейса, который позволяет независимое развитие приложения без тесной связи сервисов, моделей или действий приложения с самим уровнем API.Единый интерфейс позволяет клиенту разговаривать с сервером на одном языке, независимо от архитектурного бэкенда того или другого. Этот интерфейс должен обеспечивать неизменные стандартизованные средства связи между клиентом и сервером, такие как использование HTTP с ресурсами URI, CRUD (создание, чтение, обновление, удаление) и JSON.
Многоуровневая система
Как следует из названия, многоуровневая система — это система, состоящая из уровней, каждый из которых имеет определенные функции и ответственность.Если мы подумаем о структуре Model View Controller, каждый уровень имеет свои собственные обязанности, при этом модели определяют, как должны формироваться данные, контроллер фокусируется на входящих действиях, а представление фокусируется на выходных данных. Каждый слой является отдельным, но также взаимодействует с другим. В дизайне REST API действует тот же принцип: разные уровни архитектуры работают вместе, чтобы построить иерархию, которая помогает создать более масштабируемое и модульное приложение.
Многоуровневая система также позволяет инкапсулировать устаревшие системы и перемещать менее часто используемые функции на общий посредник, одновременно защищая от них более современные и часто используемые компоненты.Кроме того, многоуровневая система дает вам свободу перемещать системы в вашу архитектуру и из нее по мере развития технологий и услуг, повышая гибкость и долговечность, пока вы сохраняете как можно более слабую связь между различными модулями. Наличие многоуровневой системы дает существенные преимущества с точки зрения безопасности, поскольку она позволяет останавливать атаки на уровне прокси или на других уровнях, предотвращая их попадание на реальную архитектуру сервера. Используя многоуровневую систему с прокси или создав единую точку доступа, вы можете держать критические и более уязвимые аспекты вашей архитектуры за брандмауэром, предотвращая прямое взаимодействие с ними со стороны клиента.Имейте в виду, что безопасность основана не на едином решении «остановить все», а, скорее, на наличии нескольких уровней с пониманием того, что определенные проверки безопасности могут быть неудачными или их можно обойти. Таким образом, чем больше безопасности вы сможете внедрить в свою систему, тем больше у вас будет шансов предотвратить вредоносные атаки.
Код по запросу
Возможно, наименее известное из шести ограничений и единственное необязательное ограничение. Код по запросу позволяет передавать код или апплеты через API для использования в приложении.По сути, он создает интеллектуальное приложение, которое больше не зависит исключительно от собственной структуры кода. Однако, возможно, потому, что он опередил свое время, Code on Demand изо всех сил пытался принять, поскольку веб-API используются на нескольких языках, а передача кода вызывает вопросы безопасности и вызывает опасения. (Например, каталог должен быть доступен для записи, а брандмауэр должен пропускать то, что обычно может быть ограниченным контентом.)
Вместе эти ограничения составляют теорию передачи репрезентативного состояния или REST.Просматривая их, вы можете увидеть, как каждое последующее ограничение строится поверх предыдущего, в конечном итоге создавая довольно сложный, но мощный и гибкий интерфейс прикладной программы. Но самое главное, эти ограничения составляют структуру, которая работает аналогично тому, как мы получаем доступ к страницам в наших браузерах во всемирной паутине. Он создает API, который диктуется не его архитектурой, а представлениями, которые он возвращает, и API, который, хотя и не имеет состояния с архитектурой, полагается на представление, чтобы диктовать состояние приложения.
Для получения дополнительной информации о REST API Design ознакомьтесь с электронной книгой Undisturbed REST: A Guide to Designing Perfect API.
Спецификация отдельного URI для правил REST службы
Спецификация отдельного URI для правил REST службы
Для разных URI ресурса указаны разные правила REST службы. Эта функция предоставляет различные варианты обработки, обработки запросов и ответов для каждого отдельного URI ресурса.Кроме того, это избавляет от необходимости поддерживать сложную логику, используемую для обработки всех возможных путей URI ресурсов.
Используя шаблоны URI, вы можете определять различные правила REST службы для отдельных URI ресурсов. Вы определяете эти поля при создании нового правила службы REST. URI ресурса включает в себя следующие компоненты:
- Пакет услуг — экземпляр данных, который используется для поддержки развертывания служб. Дополнительные сведения о пакетах услуг см. В разделе Об экземплярах данных пакета услуг.
- Версия службы — номер версии правила службы.
- Шаблон URI — шаблон, поддерживающий буквальные и переменные параметры пути. С помощью этого компонента вы можете сопоставить URI ресурса с правилом REST службы. Для получения информации о требованиях к форматированию параметров в шаблоне URI см. Требования к компоненту шаблона URI.
В следующем списке приведены примеры различных URI ресурсов, которые можно сопоставить с правилами REST различных служб:
- api / vi / кейсы
- API / v1 / случаях / C_100
- api / v1 / кейсы / C_100 / вложения
- api / v1 / кейсы / C_100 / вложения / A_100
Для каждого URI ресурса api указывает пакет службы, v1 указывает версию службы, а текст после v1 / указывает шаблоны URI.Поскольку каждый URI ресурса t содержит отдельный шаблон URI, каждый URI ресурса сопоставляется с другим правилом REST службы.
Открыть тему с навигацией
Service REST — его конфигурация, отладка и обработка ошибок
Перед тем, как перейти к обсуждению, мы предлагаем вам ознакомиться с основами интеграции из нашей предыдущей публикации.
Мы очень рады написать и опубликовать статью о Service REST, поскольку это самая востребованная статья в нашей очереди.Перед написанием этого поста мы провели много исследований по полной реализации Service REST, и поэтому считаем, что он будет более информативным и полезным.
Давайте сначала разберемся с методами HTTP, доступными в Service REST.
Методы HTTP в службе REST
Pega поддерживает следующие методы HTTP в службе REST.
- GET
- POST
- PUT
- DELETE
- PATCH
GET
- Этот метод используется для Get / Retrieve информации из системы.
Например, Service REST для получения информации о клиенте на основе идентификатора клиента в запросе.
POST
- Этот метод используется для создания / обновления записей в системе. Pega рекомендует использовать метод POST для Create .
Например, Служба REST для создания / вставки записи о клиенте.
PUT
- Этот метод используется для создания / обновления записей в системе.
- Основное различие между PUT и POST заключается в том, что метод e PUT — это идемпотентный .Идемпотентный метод означает, что несколько идентичных запросов будут иметь тот же эффект, что и один запрос. Это больше похоже на БД Мертвые строки и Живые строки.
- Pega рекомендует использовать метод PUT для обновления .
Например, Service REST для обновления имени, фамилии, идентификатора электронной почты и номера телефона в записи о клиенте.
DELETE
Этот метод используется для удаления записей в системе. Его также можно условно использовать для обновления [Обновление исключительного пути].
Например, , Service REST для удаления записи клиента, когда клиент закрывает банковский счет, или Service REST до обновить запись клиента как неактивную [Обновление не удачного пути]
PATCH
Этот метод Работает очень похоже на ПОЛОЖИТЬ. Метод PATCH предпочтителен, когда обновление ограничено 1 или 2 столбцами. Pega рекомендует использовать метод PATCH, когда обновление минимально и известно.
Например, Dedicated Service REST для обновления идентификатора электронной почты записи о клиенте.
Архитектура REST службы
Из OSP мы разработали диаграмму последовательности операций архитектуры Архитектура /, которая изображает выполнение REST службы.
Версия службы OSP Процесс REST 😎
Бизнес-сценарий
Давайте рассмотрим приложение управления клиентами, созданное для OSP, банковской организации. Pega действует как централизованная база данных и хранит информацию о клиентах. Помимо Pega, существует несколько систем, к которым клиенты могут обращаться, чтобы обновить свою информацию в любое время.
Pega должна иметь возможность прослушивать все обновления из разных систем и сохранять эти данные в клиентской базе данных.
Этого легко добиться с помощью службы хостинга в Pega , которая обрабатывает все транзакции, связанные с клиентами. После этого внешняя система может использовать наши услуги и начать отправлять обновления, связанные с клиентами, в Pega.
Давайте быстро рассмотрим пошаговую реализацию Service REST с методом POST для создания записи клиента для каждого вызова службы.
Реализация
Pega не предоставляет мастеров для настройки Service REST. Следовательно, это должен быть ручной процесс😒.
Мы знаем, что это будет сложно, но вы не почувствуете того же, прочитав этот пост. Мы сделаем это для вас очень простым
Шаг 1: Давайте начнем с создания пакета услуг . Все наши услуги связаны с транзакциями клиентов, и хорошо сгруппировать услуги в рамках единого пакета услуг CRMContact .
Шаг 2: Когда пакет услуг будет готов, мы можем создать правило REST службы . Служба REST доступна в категории Integration-Services проводника Records .
Новое правило формы обслуживания REST.
Форма нового правила службы REST принимает следующие параметры:
Имя службы
Уникальное имя для нашей службы. Название нашей службы должно отражать фактическую цель службы.В нашем сценарии это может быть CreateContact / FetchContactDetails / UpdateContact / DeleteContact .
Пакет услуг
В этом поле указывается пакет услуг, к которому относится данная услуга. В нашем сценарии услуги будут сгруппированы в рамках пакета услуг CRMContact .
Версия службы
Мы можем изменить правила обслуживания в зависимости от потребностей бизнеса. Например, первый выпуск приложения может указывать на v1 из CreateContact , тогда как второй выпуск приложения может указывать на v2 из CreateContact .
Шаблон URL-адреса
Что такое URL-адрес конечной точки? 😳
Когда мы хотим что-то сообщить, мы называем людей по имени. Точно так же, когда система ( Connector ) хочет вызвать другую систему ( Service ), она делает это, используя URL-адрес конечной точки. Да, URL-адрес конечной точки будет специфическим для каждой службы, и клиентский компьютер использует URL-адрес конечной точки для вызова службы.
<< Системный URL >> / << Пакет услуг >> / << Версия службы >> / << Имя службы >>
Синтаксис URL конечной точки в Pega.
Что такое параметр ресурса? 😳
URL-адреса конечных точек не всегда могут быть статическими, а динамическая часть URL-адреса называется параметрами ресурса.
Здесь имя папки и имя файла являются динамическими и меняются для каждого вызова службы. Следовательно, он определяется как параметры ресурса URL-адреса конечной точки.
Теперь, возвращаясь к нашему шаблону URI, в этом поле должны быть определены параметры ресурса URL. Если URL-адрес не имеет параметров ресурса, тогда имя службы как таковое следует использовать в поле шаблона URI.
Шаблон URI нашей службы REST с параметрами ресурса. Шаблон URI нашей службы REST без каких-либо параметров ресурсов.
Шаг 3: Форма правила службы REST имеет две основные вкладки Служба и Методы . Давайте теперь посмотрим, как подробно настроить эти две вкладки.
1) Сервис
Вкладка «Сервис» в Service REST состоит из 3 разделов.
- Основная страница
- Свойства ресурса
- Параметры обработки
Первичная страница
Каждое правило службы имеет набор из полей в входящих запросах .Эти входящие запросы будут проанализированы и будут помещены в страницу буфера обмена, которая является основной страницей службы. Этот раздел позволяет нам настроить,
Page class
- Контекст класса нашей основной страницы.
- В Pega нет ограничений по настройке служб только в классах Integration ( Int-) . У нас также могут быть наши услуги в классах Data и Work в зависимости от потребностей бизнеса.
- Поскольку класс OSP-Data-CustomerInfo хранит информацию о клиентах, этот класс будет классом страницы нашего сервиса.
Преобразование данных
- Преобразование данных, упомянутое здесь, будет вызвано перед нашим сервисом. Это можно использовать для сопоставления любых дополнительных полей, кроме входящего запроса.
- В нашем сценарии мы устанавливаем несколько полей с помощью преобразования данных SetDefaultCustomerProps .
Имя страницы
- Все входящие запросы будут проанализированы и установлены под именем страницы, указанным в этом поле.
- Упомянутое здесь имя страницы будет использоваться как страница шага для действия службы .
- Pega по умолчанию заполняет это как MyServicePage , и при необходимости его можно обновить.
- Указанная здесь страница будет создана системой автоматически.
Свойства ресурса
Большая часть информации в этом разделе относится к URL-адресу службы и будет предварительно заполнена системой.
URL-адрес конечной точки службы
- В этом поле отображается URL-адрес конечной точки каждой службы, оформленной с использованием описанного выше синтаксиса.
- Этот URL-адрес конечной точки вместе с информацией , связанной с аутентификацией, должен быть передан внешней системе для успешного вызова службы.
шаблон URI
- В этом поле отображается значение, которое мы ввели в нашу форму нового правила для шаблона URI .
Параметры пути URL
- Если в шаблоне URI есть какие-либо параметры ресурса, то в этом поле будет отображаться сопоставление для каждого из этих параметров.
- В приведенном выше примере Идентификатор клиента отображается как параметр ресурса. Согласно конфигурации входящий параметр ресурса CustomerID будет сопоставлен со свойством CustomerID в MyServicePage .
Параметры обработки
В этом разделе содержатся конфигурации, которые в основном контролируют выполнение правила службы. В большинстве случаев, когда мы настраиваем сервис, этот раздел остается незамеченным.
Завершить запрос при выполнении
- Включение этой опции гарантирует, что инициатор запроса, созданный для обработки запроса, будет закрыт после завершения выполнения службы.
- Этот параметр учитывается только в том случае, если режим обработки выбран как Stateful в пакете услуг. Если службы не имеют состояния, значение в этом поле игнорируется.
Включить SLA службы с резервным действием
- Этот параметр используется для достижения повторной попытки в случае тайм-аута, когда служба выполняется синхронно.
- Давайте обсудим это подробно, когда мы обсудим обработку ошибок в службе REST в более поздней части сообщения.
Метод доступен только для чтения
- Включение этой опции не будет учитывать вызов во время вызова службы.
- Все еще запутались? 🧐 Не беспокойтесь, мы перейдем к наглядному объяснению,
Если для службы выбрана опция обработки « Метод доступен только для чтения, », история вызовов для службы не будет отслеживаться. Правило пакета службы, которое показывает список служб История вызовов службы, доступной только для чтения, всегда будет пустой.
Включить упрощенный режим буфера обмена
- Производительность буфера обмена можно улучшить во время выполнения службы с помощью параметра режима облегченного буфера обмена.
- Следующие страницы / свойства буфера обмена недоступны, когда выбран облегченный режим буфера обмена,
- Свойства, ссылающиеся на страницу данных.
- Связанные объекты.
- Указанные свойства.
- Декларативная сеть.
- Ограниченная поддержка выражений объявления / обратной и прямой цепочки.
- Отслеживание изменений для обновлений значений свойств в пользовательском интерфейсе.
Режим выполнения
- Эта опция используется для определения режима выполнения правила обслуживания.
- Выполнять синхронно: Выберите этот параметр, если служба должна обработать запрос немедленно.
- Выполнить синхронно (очередь при ошибке): Выберите этот параметр, если служба должна ставить в очередь запрос на асинхронное выполнение только в случае сбоя обработки при выполнении действия службы.Если ошибки обработки нет, результат такой же, как и при обычном синхронном запросе.
- Выполнить асинхронно (очередь на выполнение): Выберите этот параметр, если служба должна поставить в очередь запрос на асинхронное выполнение, она возвращает идентификатор элемента очереди внешнему приложению и завершает вызов службы. Об асинхронном выполнении сервиса мы можем поговорить в отдельном посте.
Мониторинг службы
- Pega предоставляет параметр OOTB для отслеживания каждого выполнения правила службы, когда этот параметр включен.
- Эту опцию можно включить на уровне Service или Service package level или DSS level service / EnableGlobalMonitoring .
Включение мониторинга службы на уровне обслуживания История вызовов, которая отслеживает выполнение каждой службы вместе с данными буфера обмена.
2) Метод
Вкладка «Методы» позволяет нам выбрать соответствующий метод HTTP и настроить сопоставление запросов, активность службы и сопоставление ответов.
Каждый метод в правиле REST службы при расширении имеет 3 раздела для настройки.
- Запрос
- Действия службы
- Ответ
Запрос
Этот раздел правил REST службы позволяет нам настроить входящее сопоставление службы.
Заголовки
- У каждого вызова службы будет несколько атрибутов, отображаемых в качестве заголовка.
- Наиболее часто используемые заголовки:
- Авторизация
- Content-Type (application / JSON, application / XML)
- Заголовки также могут иметь поля, специфичные для приложения. Например, , чтобы получить информацию о клиенте, CustomerID может быть передан в заголовке.
Строка запроса
- Прежде чем перейти к объяснению параметра строки запроса, давайте посмотрим, как поиск Google работает по ключевому слову OneStopPega ,
Это результат поиска OneStopPega из Google
- Строка запроса является частью окуляра U niform R esource L Что следует после «» в URL-адресе? ‘будет строкой запроса.Для URL может быть любое количество параметров строки запроса, разделенных « и ».
- Параметр строки запроса поддерживает загрузку фактического URL.
Данные сообщения
- В этом разделе есть фактическая логика анализа входящего запроса. Входящие запросы могут быть XML или JSON , и логика синтаксического анализа должна быть выбрана соответственно.
- В нашем сценарии входящие запросы будут в формате JSON и, следовательно, будет отображена структура анализа ниже.
Сопоставить с полем описывает логику синтаксического анализа, которая в нашем сценарии является JSON.
Сопоставить с ключом — это свойство объекта-правила, в соответствии с которым будет установлен входящий запрос.
Свойство, упомянутое в поле Map to key , может быть свойством Page (или) Page List (или) с одним значением.
- Ниже показан пример входящего запроса и структуры буфера обмена в Pega после успешного анализа входящего запроса.
{
“. CustomerInfo «: {
« CustomerID »:« OSP »,
« Имя »:« One Stop »,
« Фамилия «:1469 Pega»,
«Пега» EmailID “:” [email protected] ”
}
}
Действия службы
- Действия службы — это место, где находится наша основная бизнес-логика службы.
- В нашем сценарии нам нужна операция, которая может отображать проанализированный входящий запрос и сохранять данные в базе данных по мере необходимости.
Сервисная операция, логика которой — Создание записи клиента.
Ответ
Этот раздел правил REST службы позволяет нам настроить исходящее сопоставление службы.
Условие отклика
Условие отклика — это своего рода поле для принятия решений, в котором мы можем отображать ответы на основе различных условий.
Условия OOTB могут использоваться для обработки ошибок во время отображения, безопасности и выполнения службы.
Любые бизнес-условия можно обрабатывать с помощью Custom, если правило создано в наборе правил приложения.
Заголовки
- Подобно заголовкам во входящем запросе, мы также можем сопоставить заголовки с ответом.
- Здесь необходимо настроить отображение заголовков в ответе.
Данные сообщения
- В этом разделе есть фактическая логика исходящего сопоставления. Ответы могут быть XML или JSON , и исходящая логика должна быть выбрана соответственно.
- В нашем сценарии ответом будет JSON, поэтому исходящее сопоставление выглядит следующим образом:
Поле «Карта из » описывает структуру ответа. В нашем сценарии это JSON.
Карта из ключа — это свойство объекта-правила, в соответствии с которым будет установлен ответ.
Свойство, упомянутое в поле Map from key , может быть свойством Page (или) Page List (или) с одним значением.
- Другие необходимые поля ответа также могут быть установлены из действия службы.
- Ниже показана структура буфера обмена ответа в Pega и преобразованный ответ JSON.
{
« Сообщение «: «Запись успешно вставлена»,
« StatusCode «: »200»
}
С помощью этого сопоставления ответов мы завершаем создание и настройку нашего Сервис REST. Давайте теперь посмотрим, как выполнять обработку ошибок, тестирование и отладку в Service REST.
Обработка ошибок в службе REST
Это еще один важный аспект реализации REST службы.Из словаря OSP мы бы классифицировали обработку ошибок в службах на три типа:
- Ошибка инфраструктуры.
- Деловая ошибка.
- Ошибка тайм-аута (стратегия возврата).
Ошибка инфраструктуры
Ошибки, не относящиеся к приложению, а именно ошибка выполнения службы, ошибка безопасности, ошибка сопоставления, подпадают под эту категорию.
Ошибки инфраструктуры такого типа можно обработать на вкладке «Условие ответа» правила обслуживания.
Например, при сбое безопасности при авторизации можно задать настраиваемый ответ с более подробной информацией о причине сбоя.
Бизнес-ошибка
Ошибки, специфичные для приложения, а именно обязательная проверка полей, соблюдение свойств может обрабатываться как часть этой обработки ошибок.
Бизнес-ошибки можно обрабатывать с помощью действия службы или настраиваемого правила при условии ответа правила службы.
Логика для обработки обязательной проверки поля для поля идентификатора электронной почты
Резервная стратегия
В правилах обслуживания, начиная с Pega v7, есть еще одна интересная функция. SLA службы может быть установлен для каждого вызова службы, который будет инициироваться, если время ожидания службы непрерывно для <
Служба REST настроена с таймаутом 500 миллисекунд.
Если время выполнения службы истекает непрерывно для 3 попыток с интервалом в 10 секунд каждая, то выполняется действие, указанное как резервное действие.
Резервное действие можно настроить для каждого метода в службе.
По истечении времени ожидания обслуживания разработчику будет отправлено электронное письмо с запросом и другой необходимой информацией .
Служба тестирования REST
Тестирование REST API должно охватывать следующие аспекты
- Основные положительные тесты (счастливый путь)
- Расширенное положительное тестирование (все возможные положительные сценарии)
- Отрицательное тестирование с действительным вводом
- Отрицательное тестирование с недопустимым вводом
- Разрушающее тестирование (Возможны отрицательные сценарии приложения)
- Тесты безопасности, авторизации и разрешений (обязательно)
Для тестирования Сервисов можно использовать любой из клиентов API, например REST Client, PostMan.Мы будем использовать приложение PostMan для тестирования нашей службы CreateContact .
- Поскольку мы используем метод POST в нашей службе, выберите метод POST в PostMan и введите URL-адрес конечной точки нашей службы.
- Поскольку наша служба аутентифицирована, нам необходимо передать необходимую информацию. Если эта информация недействительна, служба возвращает 400 Код ошибки .
- Поле заголовка должно обозначать тип содержимого , который в нашем сценарии — это приложение / JSON .
URL-адрес конечной точки и информация об авторизации
- Body / PayLoad службы, которая имеет фактический запрос.
Полезная нагрузка службы CreateContact
- Когда все настройки выполнены, службу можно протестировать, нажав кнопку Отправить . При нажатии кнопки отправки служба запускается, и соответствующий ответ будет показан в PostMan.
Служба отладки REST
Служба отладки REST довольно проста по сравнению с другими правилами в Pega.Мы можем использовать трассировщик и журналы для отладки сервисов.
- Откройте правило службы, которое необходимо отладить, и выполните правило открытия трассировки. События Tracer покажут входящее сопоставление, выполнение службы и исходящее сопоставление.
- Перед отслеживанием службы убедитесь, что вы включили в трассировщике указанные ниже настройки.
- Вам не будет разрешено отслеживать услуги в производственной среде. См. Нашу статью о настройке системы, в которой объясняется, как включить трассировку службы в производственной среде.
- Мы также можем использовать метод Log-message в действиях службы для регистрации наших запросов, ответов и других исключений, если таковые имеются.
Мы подошли к концу публикации и надеемся, что вы разобрались с настройкой REST службы, ее тестированием, отладкой и обработкой ошибок в Pega.
Мы рады опубликовать статью, запрошенную @ Рави, Сухас, Раджеш, Сурадж на « Service REST in PEGA ».Если вы хотите, чтобы мы опубликовали какие-либо статьи по вашему выбору, заполните эту форму , и мы позаботимся о том, чтобы она была опубликована.
Следите за новостями об интеграции 😎
Методы HTTP для служб RESTful
Ниже более подробно рассматриваются основные методы HTTP. Щелкните вкладку для получения дополнительных сведений о желаемом методе HTTP.
Глагол POST чаще всего используется для ** создания ** новых ресурсов.В частности, он используется для создания подчиненных ресурсов. То есть подчиняться какому-то другому (например, родительскому) ресурсу. Другими словами, при создании нового ресурса POST-запрос к родительскому объекту, а служба заботится о том, чтобы связать новый ресурс с родительским, присвоить идентификатор (новый URI ресурса) и т. Д.
При успешном создании вернуть HTTP-статус 201, возвращая заголовок Location со ссылкой на вновь созданный ресурс с HTTP-статусом 201.
POST не является ни безопасным, ни идемпотентным.Поэтому рекомендуется для неидемпотентных запросов ресурсов. Выполнение двух идентичных запросов POST, скорее всего, приведет к тому, что два ресурса будут содержать одинаковую информацию.
Примеры:
- ЗАПИСЬ http://www.example.com/customers
- ЗАПИСЬ http://www.example.com/customers/12345/orders
Метод HTTP GET используется для ** чтения ** (или извлечения) представления ресурса.В «счастливом» (или безошибочном) пути GET возвращает представление в XML или JSON и код ответа HTTP 200 (OK). В случае ошибки он чаще всего возвращает 404 (НЕ НАЙДЕН) или 400 (НЕПРАВИЛЬНЫЙ ЗАПРОС).
Согласно дизайну спецификации HTTP, запросы GET (вместе с HEAD) используются только для чтения данных, а не для их изменения. Поэтому при таком использовании они считаются безопасными. То есть их можно вызывать без риска изменения или повреждения данных — однократный вызов имеет тот же эффект, что и 10-кратный вызов или вообще не вызывает.Кроме того, GET (и HEAD) идемпотентны, что означает, что выполнение нескольких идентичных запросов в конечном итоге дает тот же результат, что и один запрос.
Не раскрывайте небезопасные операции с помощью GET — он никогда не должен изменять какие-либо ресурсы на сервере.
Примеры:
- ПОЛУЧИТЬ http://www.example.com/customers/12345
- ПОЛУЧИТЬ http://www.example.com/customers/12345/orders
- ПОЛУЧИТЬ http: // www.example.com/buckets/sample
PUT чаще всего используется для ** возможности обновления **, PUT-ing к известному URI ресурса с телом запроса, содержащим недавно обновленное представление исходного ресурса.
Однако PUT также может использоваться для создания ресурса в случае, когда идентификатор ресурса выбирается клиентом, а не сервером. Другими словами, если PUT относится к URI, который содержит значение несуществующего идентификатора ресурса.Опять же, тело запроса содержит представление ресурса. Многие считают это запутанным и запутанным. Следовательно, этот метод создания следует использовать умеренно, если вообще использовать.
В качестве альтернативы используйте POST для создания новых ресурсов и предоставления определенного клиентом идентификатора в представлении тела — предположительно, для URI, который не включает идентификатор ресурса (см. POST ниже).
При успешном обновлении вернуть 200 (или 204, если не возвращает никакого содержимого в теле) из PUT.Если для создания используется PUT, при успешном создании вернуть HTTP-статус 201. Тело в ответе является необязательным — оно требует большей пропускной способности. В случае создания нет необходимости возвращать ссылку через заголовок Location, поскольку клиент уже установил идентификатор ресурса.
PUT не является безопасной операцией, поскольку он изменяет (или создает) состояние на сервере, но он идемпотентен. Другими словами, если вы создаете или обновляете ресурс с помощью PUT, а затем снова выполняете тот же вызов, ресурс все еще существует и по-прежнему находится в том же состоянии, что и при первом вызове.
Если, например, вызов PUT для ресурса увеличивает счетчик внутри ресурса, вызов больше не является идемпотентным. Иногда такое случается, и этого может быть достаточно, чтобы подтвердить, что вызов не идемпотентен. Однако рекомендуется сохранять идемпотентность запросов PUT. Настоятельно рекомендуется использовать POST для неидемпотентных запросов.
Примеры:
- PUT http://www.example.com/customers/12345
- ПОСТАВИТЬ http: // www.example.com/customers/12345/orders/98765
- ПОСТАВИТЬ http://www.example.com/buckets/secret_stuff
PATCH используется для ** изменения ** возможностей. Запрос PATCH должен содержать только изменения ресурса, а не весь ресурс.
Это похоже на PUT, но тело содержит набор инструкций, описывающих, как ресурс, находящийся в данный момент на сервере, должен быть изменен для создания новой версии.Это означает, что тело PATCH должно быть не просто измененной частью ресурса, а на каком-то языке исправлений, например JSON Patch или XML Patch.
PATCH не является ни безопасным, ни идемпотентным. Однако запрос PATCH может быть выпущен таким образом, чтобы быть идемпотентным, что также помогает предотвратить плохие результаты из-за коллизий между двумя запросами PATCH на одном и том же ресурсе в аналогичный период времени. Коллизии из нескольких запросов PATCH могут быть более опасными, чем коллизии PUT, потому что некоторые форматы исправлений должны работать с известной базовой точкой, иначе они повредят ресурс.Клиенты, использующие этот вид приложения исправления, должны использовать условный запрос, так что запрос не будет выполнен, если ресурс был обновлен с момента последнего обращения клиента к ресурсу. Например, клиент может использовать сильный ETag в заголовке If-Match в запросе PATCH.
Примеры:
- ПАТЧ http://www.example.com/customers/12345
- ПАТЧ http://www.example.com/customers/12345/orders/98765
- ПАТЧ http: // www.example.com/buckets/secret_stuff
DELETE довольно легко понять. Он используется для ** удаления ** ресурса, идентифицированного URI.
При успешном удалении вернуть HTTP-статус 200 (OK) вместе с телом ответа, возможно, представлением удаленного элемента (часто требует слишком большой пропускной способности) или завернутым ответом (см. Возвращаемые значения ниже). Либо это, либо возврат HTTP-статуса 204 (NO CONTENT) без тела ответа. Другими словами, рекомендуется использовать статус 204 без тела или ответ в стиле JSEND и статус HTTP 200.
Согласно спецификации HTTP, операции DELETE идемпотентны. Если вы УДАЛИТЕ ресурс, он будет удален. Неоднократный вызов DELETE для этого ресурса приводит к тому же: ресурс пропал. Если, скажем, вызов DELETE уменьшает счетчик (в пределах ресурса), вызов DELETE больше не идемпотентен. Как упоминалось ранее, статистика использования и измерения могут обновляться с учетом идемпотентности услуги до тех пор, пока не изменяются данные ресурсов.