REST интерфейс и HTTP запросы. Часть 1 Получение данных – метод GET
Вторая часть можно посмотреть здесь
Общие сведения
В версии платформы 8.3.5.1068, опубликованной в сентябре 2015 появился механизм интеграции 1С с внешними программами через технологию REST интерфейс. В качестве протокола доступа платформа использует протокол OData . Это открытый веб-протокол для запроса и обновления данных. Он позволяет оперировать данными, используя в качестве запросов HTTP-команды. Получать ответы в версии 8.3.5.1068 можно было только в формате Atom/XML . Однако, начиная с релиза 8.3.8.1652 в августе 2017 г. появился второй вариант получения данных в формате JSON(англ. JavaScript Object Notation) . По сравнению с XML он легко читается людьми занимает меньше места. Кроме этого все браузеры имеют встроенные средства для работы с JSON.
Работу с протоколом OData на платформе 1С: предприятие можно посмотреть в книге 1С: Руководства разработчика в главе 17 Механизмы интернет-сервисов , параграф 17.2.1 Cтандартный интерфейс OData. Можно также посмотреть примеры расширения поддержки протокола OData , реализованного в версии 8.3.8.1652 здесь.
Преимущество использования REST интерфейс. заключает в том , что для получения доступа к данным системы из внешнего приложения не требуется модификации кода прикладного решения (например, если прикладное решение стоит на поддержке). Для получения такого доступа необходимо особым образом опубликовать приложение на веб-сервере и указать, какие объекты конфигурации будут использоваться таким образом. После этого сторонние системы могут обращаться к вашему приложению с помощью HTTP запросов.
Публикация стандартного интерфейса OData выполняется с помощью диалога публикации на веб-сервере (Администрирование – Публикация на веб- сервере) и описано в книге 1С:Предприятие 8.3. “Руководство администратора”.
Важно! Для того чтобы объекты конфигурации стали доступны через стандартный интерфейс OData, необходимо разрешить это с помощью метода глобального контекста УстановитьСоставСтандартногоИнтерфейсаOData().
Механизм установки состава объектов, доступных с помощью стандартного интерфейса OData, можно выполнить в виде внешней обработки. Для этого не требуется модифицировать прикладное решение.
Для взаимодействия с внешним REST- веб-сервер из 1С:Предприятия используется имеющиеся в платформе средства работы с HTTP: объекты HTTPСоединение, HTTPЗапрос и HTTPОтвет.
В этой цикле статьей я буду показывать примеры типовых операций, использующих соответствующий HTTP-метод ;
- Получение данных – метод GET;
- Создание объекта – метод POST;
- Обновление данных : метод PATCH – в этом случае можно указывать только те свойств, которые необходимо обновить; метод PUT – в этом случае необходимо указывать все свойства сущности;
- Удаление данных – метод DELETE.
1. Примеры получения данных. HTTP-метод GET
В качестве сервера будет выступать опубликованная на веб-сервере БД с именем WebBuh (Демо-база “Бухгалтерия Предприятия 3.0”). В качестве формата обмена данных я буду использовать формат JSON. Подробнее о работе с JSON написано в документации, доступной здесь . Для получения данных из сервера HTTP-методом GET требуется создать объект ЧтениеJSON для последовательного чтения JSON-данных из файла или строки. Для организации последовательной записи объектов и текстов на сервере HTTP-методом POST PATCH PUT требуется создать объект ЗаписьJSON. Отметим, для метода DELETE не требуется JSON.
В качестве иллюстрации потокового чтения и записи JSON при обращении к REST интерфейсу я буду вызывать следующую пользовательскую функцию общего назначения ВызватьHTTPМетодНаСервере :
&НаСервере // <Описание функции> // // Параметры: // <HTTPМетод> - Строка, содержащая имя HTTP-метода для запроса ("POST"."PATCH", "PUT" ,"GET","DELETE" // <HTTPСоединение> - объект HTTPСоединение // <АдресРесурса> - Строка http-ресурса, к которому будет отправлен HTTP запрос. // <ОтправляемыеДанные> - Структура или соответствие, содержащие данные, отправляемые на указанный адрес для обработки // на сервер с использованием указанного HTTP-метода "POST" или "PATCH" или "PUT" // Возвращаемое значение: // Структура ответа сервера в зависимости от HTTPМетод // Функция ВызватьHTTPМетодНаСервере(HTTPМетод,HTTPСоединение,АдресРесурса,ОтправляемыеДанные = Неопределено) // Создание HTTPЗапрос Заголовки = Новый Соответствие(); Заголовки.Вставить("Content-Type", "application/json"); ЗапросHTTP = Новый HTTPЗапрос( АдресРесурса, Заголовки); // ЗаписьJson толка для создания и обновление данных Если HTTPМетод= "POST" или HTTPМетод="PATCH" или HTTPМетод="PUT" Тогда ЗаписьJSON = Новый ЗаписьJSON; ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Авто,"",Истина); ЗаписьJSON.УстановитьСтроку(ПараметрыJSON); ЗаписатьJSON(ЗаписьJSON, ОтправляемыеДанные); // ОтправляемыеДанные обязательны в этом случае СтрокаДляТела = ЗаписьJSON.Закрыть(); ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаДляТела,КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать); КонецЕсли; // Вызов Метода HTTPСоединение ОтветHTTP = HTTPСоединение.ВызватьHTTPМетод(HTTPМетод, ЗапросHTTP); СтруктураОтвета = Новый Структура; СтруктураОтвета.Вставить("КодСостояния", ОтветHTTP.КодСостояния); // ЧтениеJSON только для метода GET Если HTTPМетод= "GET" Тогда Попытка ЧтениеJSON = Новый ЧтениеJSON; ОтветСервера = ОтветHTTP.ПолучитьТелоКакСтроку("UTF-8"); ЧтениеJSON.УстановитьСтроку(ОтветСервера); Соответствие = ПрочитатьJSON(ЧтениеJSON,Истина); СтруктураОтвета.Вставить("ОтветСервера", Соответствие); СтруктураОтвета.Вставить("ОтветСервераНеРасшифрованный", ОтветСервера); Исключение Сообщить(ОписаниеОшибки()); Возврат Неопределено; КонецПопытки; Конецесли; Возврат СтруктураОтвета; КонецФункции // ВызватьHTTPМетодНаСервере()
Для получения от сервера в формате JSON при обращении к REST интерфейсу прикладного решения нужно в адресе ресурса указать $format=json. Либо указать MIME тип “application/json” в заголовке :
Заголовки = Новый Соответствие(); Заголовки.Вставить("Content-Type", "application/json"); АдресРесурса ="WebBuh/odata/standard.odata/?$format=json" ЗапросHTTP = Новый HTTPЗапрос(АдресРесурса, Заголовки);
Особенность глобального контекста ПрочитатьJSON(ЧтениеJSON, Истина)
Подробнее о синтаксисе ПрочитатьJSON можно посмотреть в документации платформы. Отметим здесь некоторые особенности :
- Если значение второго параметра установлено Истина, чтение объекта JSON будет выполнено в Соответствие.Если установлено Ложь, объекты будут считываться в объект типа Структура.
- При десериализации объектов JSON в структуру необходимо помнить о требованиях к ключам структуры. Если при десериализации объекта будет найдено имя свойства, недопустимое для ключа структуры, то будет вызвано исключение.
1. 1 Настройка параметров HTTP соединения
Для организации клиентской части взаимодействия с внешним REST- веб-сервер, я создал “с нуля” конфигурацию клиента на базе БСП. На этой конфигурации я создал справочник настройки параметров подключения (см Рис 1)

После нажатия кнопки Проверить ответ сервера, вызывается процедура, по которой клиент попытается получать ответ сервера. Программный код процедуры написан ниже :
&НаКлиенте Процедура ПроверитьПодключение(Команда) Адрес = Объект.АдресСервера; Пользователь = Объект.Пользователь; Пароль= Объект.Пароль; ИмяБазы = Объект.Наименование; Порт = ?(Объект.Порт <> 0,Объект.Порт,80); HTTPСоединение = Новый HTTPСоединение(Адрес,Порт,Пользователь, Пароль); АдресРесурса = ИмяБазы+ "/odata/standard.odata/$metadata"; //Вызов пользовательской функции СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса); Если СтруктураОтвета <> Неопределено Тогда ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Код состояния "+СтруктураОтвета.КодСостояния); Конецесли; КонецПроцедуры
Цель этой процедуры – Это проверка работы сервиса и правильно ли пользователь ввел параметры соединения. Для этого достаточно выполнить GET-запрос:
HTTPСоединение.ВызватьHTTPМетод(“GET”, ЗапросHTTP) ;
с использованием адреса ресурса:
АдресРесурса = ИмяБазы+ “/odata/standard.odata/“;
Проверить работы сервиса можно также в браузере с использованием
URL http://host/WebBuh/odata/standard.odata. В результате такого запроса получается только список сущностей . Для получения полного описания стандартного интерфейса OData (список доступных сущностей, их атрибутов и функций в виде XML-
документа.) необходимо выполнить GET-запрос с использованием параметра $metadata. URL http://host/WebBuh/odata/standard.odata/$metadata. Подробное описание документа можно получить по адресу http://www.odata.org/documentation/ (на английском языке).
Получать ответы можно в формате Atom/XML или JSON. Коды статусов ответа по протоколу HTTP можно посмотреть здесь. Ответы в диапазонах:
- 100-199 – информационные ответы, показывающие, что запрос клиента принят и обрабатывается.
- 200-299 – означают, что запрос клиента обработан успешно.
- 300-399 означает, что запрос не выполнен и клиенту нужно предпринять некоторые действия для удовлетворения запроса.
- 400-499 – информирует об ошибках на стороне клиентского приложения. Эти коды могут также означать, что от клиента требуется дополнительная информация.
- 500-599 – информирует об ошибке на стороне сервера, показывают, что сервер столкнулся с ошибкой и, вероятно, не сможет выполнить запрос клиента.
1.2 Поиск объекта по идентификатору
Следующая функция предназначена для поиска справочника или документа по уникальному идентификатора на сервере . Если объект найден, то функция возвращает строковое значение идентификатора (Ref_Key ) , иначе возвращает неопределено. В функцию передаются следующие параметры:
- HTTPСоединение – Объект типа HTTPСоединение
- ИмяПубликации – Имя опубликованной базы базы данных сервера
- Элемент – идентификатор сущности объекта , например, Catalog_Организации или Document_- справочник Организации.
- Идентификатор – Идентификатор объекта, который нужно искать на сервере, например, Организация.УникальныйИдентификатор()
&НаСервере Функция ПоискОбъектПоGUID (HTTPСоединение,ИмяПубликации,Элемент,УникальныйИдентификатор) GUID = Строка(УникальныйИдентификатор); // преобразуем в строку АдресРесурса = ИмяПубликации+ "/odata/standard.odata/" + Элемент+ "(guid'"+ GUID+ "')?$format=json"; //Вызов моей пользовательской функции СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса); Если СтруктураОтвета.КодСостояния >= 400 Тогда //ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+СтруктураОтвета.КодСостояния+ //ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтруктураОтвета.ОтветСервераНеРасшифрованный); Возврат неопределено; КонецЕсли; Соответствие = СтруктураОтвета.ОтветСервера; Массив= Соответствие["value"]; Если Массив = Неопределено Тогда Возврат Соответствие["Ref_Key"] Иначе Возврат Массив[0]["Ref_Key"]; КонецЕсли; КонецФункции
Параметр АдресРесурса используется для обращения к REST-сервису. Для проверки работы сервиса можно указать ресурс в браузере таким образом
http://{АдресВебСервера}/{ИмяПубликации}/odata/standard.odata/{Элемент}?{Параметры},где
- АдресВебСервера – Адрес веб-сервера, на котором опубликован сервис, например Localhost
- ИмяПубликации – имя информационной базы указанное при публикации решения
- /odata/standard.odata/ – Признак обращения к стандартному интерфейсу OData
- Элемент – идентификатор ресурса или предопределенные ресурсы. Например, Catalog_Контрагент(guid’value’).
- Параметры – параметры ресурса. Используются, например, для отбора, в принятом для HTTP-запросов: ?ключ=значение&ключ2=значение2
1.3 Поиск объекта по полям поиска
Следующая пользовательская функция предназначена для поиска объекта по полям поиска в том случае, когда объект по идентификационному номеру. Функция возражает строку Ref_Key – идентификационный номер.
&НаСервере Функция ПоискОбъектПоПолямПоиска(HTTPСоединение,ИмяПубликации, Элемент,ПоляПоиска ) Условие = ""; Для Каждого КлючЗначение из ПоляПоиска Цикл Условие = Условие + КлючЗначение.Ключ + " eq '" + КлючЗначение.Значение + "' and "; КонецЦикла; ТекстЗапроса = Лев(Условие, СтрДлина(Условие)-5); // удаляем последние 5 символов АдресРесурса= ИмяПубликации+ "/odata/standard.odata/" +Элемент+ "?$filter=" + ТекстЗапроса + "&$format=json&$select=Ref_Key"; //Вызов моей пользовательской функции СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса); Если СтруктураОтвета.КодСостояния >= 400 Тогда //ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+СтруктураОтвета.КодСостояния); //ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтруктураОтвета.ОтветСервераНеРасшифрованный); Возврат неопределено; КонецЕсли; Соответствие = СтруктураОтвета.ОтветСервера; Массив= Соответствие["value"]; Если Массив = Неопределено Тогда Возврат Соответствие["Ref_Key"] Иначе Возврат Массив[0]["Ref_Key"]; КонецЕсли; КонецФункции
Как видно из тела процедуры ПоискОбъектПоПолямПоиска , отбор начинается с ключевого слова $filter в адресе ресурса. Формальный параметр ПоляПоиска – это соответствие, которое содержит наименования и значения реквизитов.
Отметим, что наименование реквизитов порой не очевидно. Необходимо запомнить, что для справочников:
- Code – код,
- Description – Наименование
- DeletionMark – пометка удаления,
- IsFolder – признак группы,
- Parent_Key – родитель.
- Если реквизит ссылочного типа, к его имени следует добавить суффикс _Key, например Контрагент_Key.
Для документов:
- Number – номер документа,
- Date – дата документа.
Логические операции отбора
- eq — Равно; /Catalog_Города?$filter=Наименование eq ‘Главный’;
- ne — Не равно; /Catalog_Города?$filter=Наименование ne ‘Пермь’;
- gt — Больше; /Catalog_Товары?$filter=Цена gt 10;
- ge — Больше или равно; /Catalog_Товары?$filter=Цена ge 10;
- lt — Меньше; /Catalog_Товары?$filter=Цена lt 10;
- le — Меньше или равно; /Catalog_Товары?$filter=Цена le 10;
- or — Логическое ИЛИ; /Catalog_Товары?$filter=Цена lt 10 or Цена gt 100;
- and — Логическое И; /Catalog_Товары?$filter=Цена gt 10 and Цена lt 100;
- not — Отрицание; /Catalog_Товары?$filter=not (Цена eq 10);
Отметим, также, что значение фактического параметра Элемент ( или сущность)) , который я передаю на функцию формируется по следующему правилу:
ПрефиксИмени_ИмяОбъектаКонфигурации_СуффиксИмени.
С помощью стандартного интерфейса OData можно получить доступ к следующим объектам (ПрефиксИмени):
- Справочник — Catalog;
- Документ — Document;
- Журнал документов — DocumentJournal;
- Константа — Constant;
- План обмена — ExchangePlan;
- План счетов — ChartOfAccounts
- План видов расчета — ChartOfCalculationTypes;
- План видов характеристик — ChartOfCharacteristicTypes;
- Регистр сведений — InformationRegister;
- Регистр накопления — AccumulationRegister;
- Регистр расчета — CalculationRegister;
- Регистр бухгалтерии — AccountingRegister;
- Бизнес-процесс — BusinessProcess;
- Задача — Task.
ИмяОбъектаКонфигурации — свойство «Имя» объекта конфигурации так, как оно задано в конфигураторе.
СуффиксИмени — нужен для уточнения имени ресурса, необязателен, может принимать следующие значения:
- Имя табличной части объекта;
- Имя виртуальной таблицы объекта;
- RowType — строка табличной части объекта;
- RecordType — отдельная запись регистра.
Параметры обращения к ресурсам
После формирования имени ресурса нужно определить параметры обращения к ресурсу, например, ?$filter=Значение&$format=json&$select=Ref_Key ,
- $filter — отбор при получении данных
- $format — указывает формат возвращаемых данных,
- $select — перечисление свойств сущности, которые попадут в результат запроса;
- $metadata — возвращает описание стандартного интерфейса OData (используется без указания суффикса имени, пример на одном из изображений выше);
- $top — ограничение количества возвращаемых записей ;
- $skip — убирает из результата запроса указанное количество записей ;
- $count — возвращает количество записей в выборке запроса;
- $inlinecount=allpage(=none) — добавляет в результат запроса информацию о количестве записей
- $orderby=<Реквизит1> asc, <Реквизит2> desc — сортировка результата запроса
- alloweOnly — только разрешенные (используется без знака «$»).
1.4 Получить массив записей регистра сведений
Посмотрим пример получения массив записей регистра сведения ФИОФизическихЛиц, например историю изменения ФИО физического лица
ИмяПубликации ="WebBuh"; Элемент = "InformationRegister_ФИОФизическихЛиц"; Период = Неопределено; ДанныеСсылочногоТипа = Новый Структура(); ДанныеСсылочногоТипа.Вставить("ФизическоеЛицо",ФизическоеЛицо_Key); ДанныеНЕСылочногоТипа= Новый Структура(); ДанныеНЕСылочногоТипа.Вставить("ФизическоеЛицо_Type", "StandardODATA.Catalog_ФизическиеЛица") Массив = ПолучитьНаборЗаписиРегистраСведений(HTTPСоединение,ИмяПубликации,Элемент, Период ,ИзмеренияСсылочногоТипа, ИзмеренияНЕСылочногоТипа )
Тело функции ПолучитьНаборЗаписиРегистраСведений, которая вызывается в этом примере показано ниже
&НаСервере Функция ПолучитьНаборЗаписиРегистраСведений(HTTPСоединение,ИмяПубликации,Элемент, Период =Неопределено ,ИзмеренияСсылочногоТипа= Неопределено, ИзмеренияНЕСылочногоТипа = Неопределено) ТекстЗапроса =""; Если Период <> Неопределено Тогда ФорматированныйПериод = Формат(Период,"ДФ=yyyy-MM-ddTHH:mm:ss"); ТекстЗапроса = "Period = datetime'"+ ФорматированныйПериод + "'" ; КонецЕсли; Если ИзмеренияСсылочногоТипа <> Неопределено Тогда Для Каждого КлючЗначение из ИзмеренияСсылочногоТипа Цикл Запитая = ?(ЗначениеЗаполнено(ТекстЗапроса), "," ,""); ТекстЗапроса = ТекстЗапроса + Запитая + КлючЗначение.Ключ + "=guid('"+ КлючЗначение.Значение + "')"; КонецЦикла; КонецЕсли; Если ИзмеренияНЕСылочногоТипа<> Неопределено Тогда Для Каждого КлючЗначение из ИзмеренияНЕСылочногоТипа Цикл Запитая = ?(ЗначениеЗаполнено(ТекстЗапроса), "," ,""); ТекстЗапроса = ТекстЗапроса + Запитая + КлючЗначение.Ключ + "=" + КлючЗначение.Значение; КонецЦикла; КонецЕсли; АдресРесурса= ИмяПубликации+ "/odata/standard.odata/" + Элемент + "("+ ТекстЗапроса+ + ")?$format=json"; //Вызов моей пользовательской функции СтруктураОтвета = ВызватьHTTPМетодНаСервере("GET",HTTPСоединение,АдресРесурса); Если СтруктураОтвета.КодСостояния >= 400 Тогда //ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+СтруктураОтвета.КодСостояния); //ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтруктураОтвета.ОтветСервераНеРасшифрованный); Возврат неопределено; КонецЕсли; Соответствие = СтруктураОтвета.ОтветСервера; Массив= Соответствие["value"]; Если Массив = Неопределено Тогда Возврат Соответствие; Иначе Возврат Массив; КонецЕсли; КонецФункции
REST интерфейс и HTTP запросы. Часть 2 Создание и изменение объекта