REST интерфейс и HTTP запросы. Часть 2  Создание и изменение объекта

Печать (Ctrl+P)
Первая часть этой статьи REST интерфейс и HTTP запросы. Часть 1  Получение данных – метод GET  содержит общую информацию об использовании механизма интеграции REST интерфейс из имеющих на диске ИТС материалов , а также некоторые практические примеры  использования  HTTP метода получения данных.

Во второй части я буду рассказывать особенность  организации последовательной записи объектов  REST интерфейс  методом  HTTP соединения:

ОтветHTTP = HTTPСоединение.ВызватьHTTPМетод( HTTPМетод, ЗапросHTTP)

При иллюстрации всех примеров я буду обращаться  к следующей глобальной пользовательской функции ВызватьHTTPМетодНаСервере.

 &НаСервере
 // <Описание функции>
 //
 // Параметры:
 //  <HTTPМетод>  - Строка, содержащая имя HTTP-метода для запроса ("POST"."PATCH", "PUT" ,"GET","DELETE"
 //  <HTTPСоединение>  - объект HTTPСоединение. Если не определено, то создается из параметров соединения
// <ПараметрыСоединения> - Структура параметров соединения 
 //  <АдресРесурса>  - Строка http-ресурса, к которому будет отправлен HTTP запрос.
 //  <ОтправляемыеДанные>  - Структура или соответствие, содержащие данные, отправляемые на указанный адрес для обработки  
 //                     на сервер с использованием указанного HTTP-метода "POST" или "PATCH" или  "PUT" 
 // Возвращаемое значение:
 //   Структура ответа сервера в зависимости от HTTPМетод
 //
 Функция ВызватьHTTPМетодНаСервере(HTTPМетод,HTTPСоединение = Неопределено ,ПараметрыСоединения, АдресРесурса,ОтправляемыеДанные = Неопределено) Экспорт
// 1. Создание HTTPСоединение 
Если HTTPСоединение = Неопределено Тогда
HTTPСоединение = Новый HTTPСоединение(ПараметрыСоединения.Сервер,ПараметрыСоединения.Порт,
                                      ПараметрыСоединения.Пользователь, ПараметрыСоединения.Пароль);
КонецЕсли; 
 // 2. Создание HTTPЗапрос
Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "application/json");
ЗапросHTTP = Новый HTTPЗапрос( АдресРесурса, Заголовки);
 // 3. ЗаписьJson толка для создания и обновление данных
Если HTTPМетод= "POST" или "PATCH" или "PUT" Тогда
	ЗаписьJSON = Новый ЗаписьJSON; 
	ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Авто,"",Истина);	
	ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
	ЗаписатьJSON(ЗаписьJSON, ОтправляемыеДанные); // ОтправляемыеДанные обязательны в этом случае
	СтрокаДляТела = ЗаписьJSON.Закрыть();
	ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаДляТела,КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
КонецЕсли;
 //  4  Вызов Метода HTTPСоединение
ОтветHTTP = HTTPСоединение.ВызватьHTTPМетод(HTTPМетод, ЗапросHTTP);
  СтруктураОтвета = Новый Структура;
  СтруктураОтвета.Вставить("КодСостояния", ОтветHTTP.КодСостояния);
  // 5. ЧтениеJSON только для метода GET 
Если HTTPМетод = "GET"  Тогда
    ЧтениеJSON = Новый ЧтениеJSON;
    ОтветСервера = ОтветHTTP.ПолучитьТелоКакСтроку("UTF-8");
    ЧтениеJSON.УстановитьСтроку(ОтветСервера);
    Соответствие = ПрочитатьJSON(ЧтениеJSON,Истина);
    СтруктураОтвета.Вставить("ОтветСервера", Соответствие);
    СтруктураОтвета.Вставить("ОтветСервераНеРасшифрованный", ОтветСервера);
Конецесли;
 // 6. Сообщим пользователю об

Если ОтветHTTP.КодСостояния < 200 и  ОтветHTTP.КодСостояния >= 300 Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Элемент+ " Ошибка "+ ОтветHTTP.КодСостояния+ символы.ПС+
        ОтветHTTP.ПолучитьТелоКакСтроку("UTF-8"));
КонецЕсли;
Возврат СтруктураОтвета;
   КонецФункции // ВызватьHTTPМетодНаСервере()

 

Основные особенности  программного кода этой функции:

  1. Не обязательно создавать HTTP-Соединение для  каждого HTTP-Запроса. Однако, я рекомендую создавать каждый раз новое HTTP-Соединение для каждого  HTTP-Запроса.   Если не удалить  HTTPСоединение от предыдущего   HTTP -Запроса, то платформа 1С: предприятие может некорректно обрабатывать новый  метод  HTTP-Запрос со старым HTTP -Соединением ,  Например, если сначала удалить запись в регистре сведения, а  потом добавить новую запись методом POST при одном и том же HTTP -Соединении, то  1С  может заменить   метод POST на метод PUT в результате  сервер возвращает код ответа 405 – Использованный HTTP метод запрещен в данном контексте
  2. Я использую формат  JSON для организации чтения и записи данных.  Подробнее о работе с JSON написано в документации здесь .  Для записи объектов и текстов  на сервере  HTTP-методом POST, PATCH, PUT   я использую  объект ЗаписьJSON,  а для получения данных  HTTP-методом GET –  ЧтениеJSON .   Отметим, для  метода DELETE  не требуется JSON.
  3. Для записи ( и получения) данных в формате JSON при обращении к REST интерфейсу прикладного решения нужно  в адресе ресурса указать $format=json. Либо указать MIME тип “application/json” в заголовке, например :
Заголовки = Новый Соответствие(); 
Заголовки.Вставить("Content-Type", "application/json");
АдресРесурса ="WebBuh/odata/standard.odata/?$format=json"
ЗапросHTTP = Новый HTTPЗапрос(АдресРесурса, Заголовки);

4 . Первый параметр АдресРесурса объекта  ЗапросHTTP  является строкой сложной конструкции для программиста и часто на ней делается ошибка в результате которого метод  HTTPСоединение.ВызватьHTTPМетод(HTTPМетод, ЗапросHTTP)  возвращает статус в диапазоне 400-499, который  информирует об ошибках на стороне клиентского приложения. Эти коды могут также означать, что от клиента требуется дополнительная информация.  Коды статусов ответа по протоколу HTTP  можно посмотреть здесь 

Например, код 405 – Использованный HTTP метод запрещен в данном контексте часто связано с тем,  клиент выполняет неверное действие из-за неправильного составленного адреса ресурса в объекте  ЗапросHTTP 

5. Я сообщаю пользователю об ошибке в программном коде этой функции, когда получаю код ответа НЕ пределах 200-299.    Дело в том, есть случай когда код ответа не равно 200, а 204 например и это не ошибка. Такой код можно получить, например  если искомый ответ не найден по полям поиска или идентификационный номер.

Примеры использования  HTTP метод  POST

В качестве сервера будет выступать опубликованная на веб-сервере БД с именем WebBuh  (Демо-база “Бухгалтерия Предприятия 3.0”).

Пример №1   Создать новый элемент справочника если он не найден  по идентификационному номеру или по полям поиска

При обмене данными , часто возникает вопрос о создании нового объекта справочника, только в том случае если его.   Сначала я буду искать его в базе приемника  по идентификационному номеру, а затем по полям поиска. Если его нет , то я его добавлю его в базе приемника с таким же идентификационный номер как в базе источника . Для иллюстрации этого примера я использую  простой  справочник, который имеет только код и наименования, например  Классификатор Стран Мира

// Параметры соединения будем считать, что они определены и база публикации WebBuh существует!
 
GUID= Строка(Страна.УникальныйИдентификатор()) ;
ПоляПоиска= Новый Соответствие();
ПоляПоиска.Вставить("Description",Страна.Наименование);

//1. Поиск по УИДу
Ref_Key="";
АдресРесурса ="WebBuh/odata/standard.odata/Catalog_СтраныМира (guid'"+ GUID+ "')?$format=json&$select=Ref_Key";
Ответ = ВызватьHTTPМетодНаСервере("GET",Неопределено ,ПараметрыСоединения, АдресРесурса,Неопределено);
Массив = Ответ.Соответствие["value"];
Если Массив = Неопределено Тогда
Ref_Key=  Ответ.Соответствие["Ref_Key"];
ИначеЕсли  Массив.Количество()>0 Тогда
Ref_Key Массив[0]["Ref_Key"];
КонецЕсли;
Если НЕ ЗначениеЗаполнено (Ref_Key) Тогда
// 2. Поиск по полям поиска
ТекстЗапроса = "";
Для Каждого КлючЗначение из ПоляПоиска Цикл
ТекстЗапроса = ТекстЗапроса + КлючЗначение.Ключ + " eq '" + КлючЗначение.Значение + "' and ";
КонецЦикла;
ТекстЗапроса = Лев(ТекстЗапроса, СтрДлина(ТекстЗапроса)-5);
АдресРесурса= "WebBuh/odata/standard.odata/Catalog_СтраныМира?$filter=" + ТекстЗапроса + "&$format=json&$select=Ref_Key";
Ответ = ВызватьHTTPМетодНаСервере("GET",Неопределено ,ПараметрыСоединения, АдресРесурса,Неопределено);
Массив = Ответ.Соответствие["value"];
Если Массив = Неопределено Тогда 
Ref_Key=  Ответ.Соответствие["Ref_Key"]; 
ИначеЕсли Массив.Количество()>0 Тогда 
Ref_Key =  Массив[0]["Ref_Key"];
 КонецЕсли;
 КонецЕсли;
ДанныеСправочника = Новый соответствие(); 
ДанныеСправочника.Вставить("Description",Страна.Наименование); 
ДанныеСправочника.Вставить("Code",Страна.Код);
Если ЗначениеЗаполнено (Ref_Key) Тогда
//метод PATCH"
АдресРесурса ="WebBuh/odata/standard.odata/Catalog_СтраныМира (guid'"+ GUID+ "')?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("PATCH",Неопределено ,ПараметрыСоединения, АдресРесурса,ДанныеСправочника);
Иначе //метод POST
ДанныеСправочника.Вставить("Ref_Key",GUID);
АдресРесурса= "WebBuh/odata/standard.odata/Catalog_СтраныМира?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("POST",Неопределено ,ПараметрыСоединения, АдресРесурса,ДанныеСправочника);
КонецЕсли;

Пример №2 Запись в периодическом регистре сведения

В этом примере будет показано как выполнить запись в периодическом и независимом  регистре сведения. Работа с зависимыми   от  документа  регистрами не имеет практического смысла, так как запись в этих регистрах происходит  в процедуре обработки проведения в  модуле объекта документа, которая вызывается при проведении документа.

В качестве примера я буду использовать регистр сведения  Документы физических лиц.

Рис 1 Структура регистра сведения Документы физ лиц

 Данный регистр является независимым и периодическим в пределах дня.

Особенность записи регистра через протокол  odata с помощью технологии интеграции Rest – интерфейс  платформы 1С  заключается в том,  что отсутствие режим замещения  существующей записи с тем же набором значений измерений регистра и с тем же периодом (для периодических регистров). Иными словами,  если запись регистра сведений с таким набором существует, то невозможно выполнять замещение и приходится сначала удалить запись, а затем добавить.  Возможно в будущих платформах 1С такая  возможность появится .Однако, на сколько мне известно последнее  расширение поддержки протокола OData  Реализовано в версии 8.3.8.1652.

Итак, поскольку  через  протокол  OData запись будет только дописана , то метод PATCH, PUT  не применимы для сущности Регистр сведения.  Попытка применять эти методы PATCH  и  PUT  вызывает  код  ответа сервера 405 – Использованный HTTP метод запрещен в данном контексте.  Аналогично ситуация возникает при попытке применять метод POST  в периодическом регистре  с существующей записью   с тем же периодом.

В следующем программном коде, мы будем выполнять сначала метод DELETE,  а затем  метод POST.

Для сокращения  программного кода будем  считать, что все  объекты ссылочного типа (ВидДокумента_Key и ФизическоеЛицо_Key) , на которые ссылается регистр сведения   добавлены в базе приемника с помощью программного кода примера №1

//1 Подготовим Адрес ресурса для удаления
ДанныеСсылочногоТипа = Новый Структура();
ДанныеСсылочногоТипа.Вставить("ВидДокумента_Key",ВидДокумента_Key);
ДанныеСсылочногоТипа.Вставить("Физлицо_Key",ФизическоеЛицо_Key);
ДанныеНЕСылочногоТипа = Неопределено;
Период = ТекущаяДата();
ТекстЗапроса="";
Если Период <> Неопределено Тогда
ФорматированныйПериод = Формат(Период,"ДФ=yyyy-MM-ddTHH:mm:ss");
ТекстЗапроса = ТекстЗапроса+ "Period = datetime'"+ ФорматированныйПериод+ "'" ; 
КонецЕсли;
Если ДанныеСсылочногоТипа <> Неопределено Тогда
Для Каждого КлючЗначение из ДанныеСсылочногоТипа Цикл
Запитая= ?(ЗначениеЗаполнено(ТекстЗапроса),",",""); 
ТекстЗапроса = ТекстЗапроса + Запитая+ КлючЗначение.Ключ + "=guid'"+ КлючЗначение.Значение+ "'";
КонецЦикла;
КонецЕсли;
Если ДанныеНЕСылочногоТипа <> Неопределено Тогда
Для Каждого КлючЗначение из ДанныеНЕСылочногоТипа Цикл
Запитая= ?начениеЗаполнено(ТекстЗапроса),",","");
ТекстЗапроса = ТекстЗапроса + Запитая + КлючЗначение.Ключ + "=" + КлючЗначение.Значение; 
КонецЦикла;
КонецЕсли;

АдресРесурса= "WebBuh/odata/standard.odata/InformationRegister_ДокументыФизическихЛиц(" + ТекстЗапроса+ ")?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("DELETE",Неопределено ,ПараметрыСоединения, АдресРесурса,Неопределено);

//2 Подготовим данные для новой записи
ДанныеДляЗаписи = Новый Структура();
ДанныеДляЗаписи.Вставить("Period",Период);
ДанныеДляЗаписи.Вставить("ВидДокумента_Key",ВидДокумента_Key); 
ДанныеДляЗаписи.Вставить("Физлицо_Key",ФизическоеЛицо_Key);
ДанныеДляЗаписи.Вставить("Серия",СерияДокумента);
ДанныеДляЗаписи.Вставить("Номер",НомерДокумента);
ДанныеДляЗаписи.Вставить("ДатаВыдачи",ДатаВыдачиДокумента);
ДанныеДляЗаписи.Вставить("СрокДействия",СрокДействияДокумента);
ДанныеПаспорта.Вставить("КемВыдан",КемВыданДокумент);
АдресРесурса= "WebBuh/odata/standard.odata/InformationRegister_ДокументыФизическихЛиц?$format=json";
Ответ = ВызватьHTTPМетодНаСервере("POST",Неопределено ,ПараметрыСоединения, АдресРесурса,ДанныеДляЗаписи);


 

Продолжение следует …….

Previous Article
Next Article

4 Replies to “REST интерфейс и HTTP запросы. Часть 2  Создание и изменение объекта”

  1. Сергей

    Спасибо за статьи ваши.

    Если можно – один вопрос по созданию записей в РС.
    Удаление проходит без проблем, а вот запись вылетает с ошибкой “Использованный HTTP метод запрещен в данном контексте”, но при этом если перед записью снова получить соединение – то всё проходит без ошибок, запись создается… Почему так может происходить?

  2. Сергей

    Нашел конкретно из-за чего падает – выше по коду я в этом же соединении использую метод PATCH при нахождении измерения (ссылки), чтобы реквизиты в ней актуализировать. И после этого если не пересоздавать соединение – то падает с вышеуказанной ошибкой. Если метод PATCH не использовать в этом соединении – то ошибки нет. Вот такая “особенность”.

    • master1c8

      Да. Конечно. это ошибка. Правильно так : Если HTTPМетод= “POST” или HTTPМетод=“PATCH” или HTTPМетод=“PUT” Тогда

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.