REST API ( Representational State Transfer ) – архитектурный стиль для передачи данных в распределенных сетевых приложениях. REST не имеет какого-то одного стандарта, но при этом должны соблюдаться имеет основные принципы:
1. Архитектура клиент-сервер;
2. Единый интерфейс;
3. Отсутствие состояния между запросами;
4. Кешируемость;
5. Слои;
6. Код по требованию;
Думаю, что более полно о Rest API можно почитать в советующей литературе. Нет смысла копипастить это с других сайтов. Мы же
рассмотрим прикладную задачу по получению данных из внешних систем при помощи REST API. Для примера будем общаться с популярной сегодня системой JIRA
Первоначально нам потребуется настроить соединение:
- Переходим в транзакцию SM59;
2. Нажимаем создать обратите внимание на «Тип соединения» в данном случае должен быть G – HTTP – связь с внешним сервером;
3. На вкладке Технические параметры вводим вводим хост и порт
4. Вводим данные пользователя в целевой системе
5. Указываем дополнительные настройки:
Обратите внимание, что в вашем случае настройки могут отличаться.
Далее надо немного покодить. Для обмена данными необходимо создать клиент.
Создаем объект:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
DATA lv_jira_dest TYPE rfcdest VALUE 'Z_TEST_RFC'. "HTTP клиент cl_http_client=>create_by_destination( EXPORTING destination = lv_jira_dest " Logical destination (specified in function call) IMPORTING client = DATA(lo_http_client) " HTTP Client Abstraction EXCEPTIONS OTHERS = 1 ). IF sy-subrc <> 0. ENDIF. "Rest клиент DATA(lo_rest_client) = NEW cl_rest_http_client( io_http_client = lo_http_client ). |
Определяемся с тем, что мы хотим сделать. От этого зависит тип запроса.
GET - получение данных
PUT - обновление данных
POST – создание
DELETE – удаление
Примеры работы с Jira API
Получение данных задачи
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
"""""GET запрос Для получения данных по номеру задачи в Jira можно использовать такой запрос. Где 'XXXX-0001'– номер искомой задачи в JIRA DATA(lv_value) = |/rest/api/2/search?jql='key'='XXXX-0001'|. "задаем заголовок запроса lo_rest_client->if_rest_client~set_request_header( EXPORTING iv_name = if_http_header_fields_sap=>request_uri " Header Name iv_value = lv_value "' Сюда вставляете ваш запрос ' ). TRY. "выполняем запрос lo_rest_client->if_rest_client~get( ). CATCH cx_rest_client_exception INTO DATA(lo_error). ENDTRY. "проверяем статус и возвращаем результат DATA(ls_status) = lo_rest_client->if_rest_client~get_status( ). DATA(lv_response) = lo_rest_client->if_rest_client~get_response_entity( )->get_string_data( ). |
В переменной ls_status – получаем статус запроса. На его основе можем сделать вывод о наличии или отсутствии ошибки.
В переменной lv_response получаем ответ в JSON формате со всеми данными страницы, его надо десериализовать . Если кратко, то используем класс /ui2/cl_json или подобный.
Получение данных Remote Issue Links (удаленных ссылок) - тот же самый GET запрос, но с небольшим дополнением:
1 |
DATA(lv_value) = |/rest/api/2/search?jql='key'='XXXX-0001'/remotelink|. |
Получение комментариев задачи
По умолчанию JIRA API не отдает поля не участвующие в поиске, для этого надо сделать GET запрос:
1 |
/rest/api/2/issue/{issueIdOrKey}/comment |
Но в моем случае такое не сработало. Пришлось для получения комментариев, использовать такой запрос:
1 |
|/rest/api/2/search?jql='key'='XXXX-NNNN'&fields=comment| |
Изменение поля на странице Jira
Следующим этапом будет изменение поля на странице Jira. Примечание: для этого надо чтобы поле было отображено на странице, иначе возвращает ошибку.
Используем PUT запрос
Страница с примерами
В общем случае JSON выглядит следующим образом:
1 2 3 4 5 |
{ "update" : { "components" : [{"set" : [{"name" : "Engine"}, {"name" : "Trans/A"}]}] } } |
У нас поле простое, поэтому вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
DATA(lv_json ) = {"update":{"customfield_17851":[{"set":"New value"}]}}. DATA(lv_value) = ‘/rest/api/2/issue/XXXX-0001’. * Формируем хедер (URI + params) lo_rest_client->set_request_header( iv_name = if_http_header_fields_sap=>request_uri " Header Name iv_value = lv_uri ). * Тело запроса DATA(lo_body) = lo_rest_client->create_request_entity( ). lo_body->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json it_parameter = VALUE #( ( name = 'charset' value = 'UTF-8' ) ) ). lo_body->set_string_data( lv_json ). lo_rest_client->put( lo_body ). "проверяем статус и возвращаем результат DATA(ls_status) = lo_rest_client->if_rest_client~get_status( ). DATA(lv_response) = lo_rest_client->if_rest_client~get_response_entity( )->get_string_data( ). |
Создание подзадачи в Jira
Используем POST запрос
Делаем сериализацию. В структуре ls_subtask_data – вся информацию о создаваемой задаче
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
DATA(lv_json) = /ui2/cl_json=>serialize( EXPORTING pretty_name = /ui2/cl_json=>pretty_mode-low_case "camel_case data = ls_subtask_data ). Вот такой json получим в результате: {"fields": {"project":{"key":"SAPHCM"}, "parent":{"key":"SAPHCM-XXXX"}, "summary":"Name new subtask", "description":"Description info", "issuetype":{"id":"5"}, <- тип говорит на м о том, что это подзадача "assignee":{"name":"Ivanov-II"} } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
DATA(lv_value) = ‘/rest/api/2/issue/XXXX-0001’. * Формируем хедер (URI + params) lo_rest_client->set_request_header( iv_name = if_http_header_fields_sap=>request_uri " Header Name iv_value = lv_uri ). * Тело запроса DATA(lo_body) = lo_rest_client->create_request_entity( ). lo_body->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json it_parameter = VALUE #( ( name = 'charset' value = 'UTF-8' ) ) ). lo_body->set_string_data( lv_json ). lo_rest_client->post( lo_body ). "проверяем статус и возвращаем результат DATA(ls_status) = lo_rest_client->if_rest_client~get_status( ). DATA(lv_response) = lo_rest_client->if_rest_client~get_response_entity( )->get_string_data( ). |
Смена статуса задачи Jira
Со статусами есть особенность, мы не можем их менять в произвольном порядке. Все статусы двигаются по статусной схеме. Поэтому иногда полезно получить список возможных переходов и уже после
Немного меняется адрес. В данном случае от выглядит так /rest/api/2/issue/ХХХХ-YYYY/
Для поиска всех возможных переходов выполним следующий GET запрос
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
DATA(lv_value) = |/rest/api/2/issue/ХХХХ-YYYY/transitions|. "задаем заголовок запроса lo_rest_client->if_rest_client~set_request_header( EXPORTING iv_name = if_http_header_fields_sap=>request_uri " Header Name iv_value = lv_value "' Сюда вставляете ваш запрос ' ). TRY. "выполняем запрос lo_rest_client->if_rest_client~get( ). CATCH cx_rest_client_exception INTO DATA(lo_error). ENDTRY. "проверяем статус и возвращаем результат DATA(ls_status) = lo_rest_client->if_rest_client~get_status( ). DATA(lv_json) = lo_rest_client->if_rest_client~get_response_entity( )->get_string_data( ). |
Получим подобный ответ со списком статусов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
{"expand":"transitions","transitions":[ {"id":"11", "name":"In Progress", "to":{"self":"https://jira….", "description":"В работе", "iconUrl":"https://jira....", "name":"В работе", "id":"3", "statusCategory":{"self":"https://jira...", "id":4, "key":"indeterminate", "colorName":"yellow", "name":"В работе"}}}, {"id":"61", "name":"Cancelled", "to":{"self":"https://jira…, "description":"", "iconUrl":"https://jira.....gif", "name":"Cancelled", "id":"13296", "statusCategory":{ "self":"https://jira.....", "id":3, "key":"done", "colorName":"green", "name":"Выполнено"}}} ] } |
Для смены статуса используем POST запрос
/rest/api/2/issue/XXXXX-YYYY/
{ "transition": { "id": "NN" } } - где NN - ID нашей операции.