Skip to content

Commit

Permalink
Пачка доработок (#93)
Browse files Browse the repository at this point in the history
* feat: Упрощение разработки своих парсеров и их тестов за счет быстрого создания мока ответа
#71

* test: задействование НовыйОтвет в тесте

* feat: КакИсключение - новый парсер Ответа
+ задействование КакИсключение
+ журналирование строки запроса и части тела ответа (без тела запроса)
+ хранение промежуточных ошибок при проблемах сети и редиректах
#84 #89

* feat: версия поднята до 2.4.2
из-за добавленных новых методов API
  • Loading branch information
zeegin authored Nov 17, 2021
1 parent 2366919 commit 2b24c16
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 44 deletions.
187 changes: 147 additions & 40 deletions src/ru/CommonModules/КоннекторHTTP/Ext/Module.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//
// URL: https://github.com/vbondarevsky/Connector
// e-mail: vbondarevsky@gmail.com
// Версия: 2.3.2
// Версия: 2.4.2
//
// Требования: платформа 1С версии 8.3.10 и выше

Expand Down Expand Up @@ -453,6 +453,40 @@

КонецФункции

// Пакет ответа результата вызова метода HTTP.
//
// Возвращаемое значение:
// * Метод - Строка - имя HTTP-метода запроса
// * URL - Строка - итоговый URL, по которому был выполнен запрос.
// * КодСостояния - Число - Код состояния ответа..
// * Заголовки - Соответствие - Заголовки ответа.
// * Тело - ДвоичныеДанные - Тело ответа.
// * Кодировка - Строка - код кодировки ответа.
// * ВремяВыполнения - Число - время выполнения запроса в миллисекундах.
// * ЭтоПостоянныйРедирект - Булево - указывает что это постоянный редирект.
// * ЭтоРедирект - Булево - указывает что это редирект.
// * Cookies - Соответствие - хранилище cookies.
// * Ошибки - Массив Из Строка - Список ошибок возникших в ходе выполнения запроса.
//
Функция НовыйОтвет() Экспорт

Результат = Новый Структура;
Результат.Вставить("Метод", "GET");
Результат.Вставить("URL", "");
Результат.Вставить("КодСостояния", 600); // Сетевая ошибка (>500)
Результат.Вставить("Заголовки", Новый Соответствие);
Результат.Вставить("Тело", Base64Значение(""));
Результат.Вставить("Кодировка", "utf-8");
Результат.Вставить("ВремяВыполнения", Неопределено);
Результат.Вставить("ЭтоПостоянныйРедирект", Ложь);
Результат.Вставить("ЭтоРедирект", Ложь);
Результат.Вставить("Cookies", Новый Соответствие);
Результат.Вставить("Ошибки", Новый Массив);

Возврат Результат;

КонецФункции

#КонецОбласти

#КонецОбласти
Expand All @@ -462,7 +496,7 @@
// Возвращает ответ сервера в виде десериализованного значения JSON.
//
// Параметры:
// Ответ - См. ВызватьМетод
// Ответ - См. НовыйОтвет
// ПараметрыПреобразованияJSON - Структура - задает параметры преобразования JSON.
// * ПрочитатьВСоответствие - Булево - Если Истина, чтение объекта JSON будет выполнено в Соответствие.
// Если Ложь, объекты будут считываться в объект типа Структура.
Expand Down Expand Up @@ -490,29 +524,19 @@
// Структура - если ПараметрыПреобразования.ПрочитатьВСоответствие = Ложь.
//
Функция КакJson(Ответ, ПараметрыПреобразованияJSON = Неопределено) Экспорт

Попытка
Возврат JsonВОбъект(РаспаковатьОтвет(Ответ), Ответ.Кодировка, ПараметрыПреобразованияJSON);
Исключение
ТекстОтвета = КакТекст(Ответ);
МаксимальнаяДлинаТекстаИсключения = 1000;
Если СтрДлина(ТекстОтвета) <= МаксимальнаяДлинаТекстаИсключения Тогда
ТекстИсключения = ТекстОтвета;
Иначе
ПоловинаМаксимальнойДлиныТекстаИсключения = МаксимальнаяДлинаТекстаИсключения / 2;
ТекстИсключения = Лев(ТекстОтвета, ПоловинаМаксимальнойДлиныТекстаИсключения);
ТекстИсключения = ТекстИсключения + Символы.ПС + "..." + Символы.ПС;
ТекстИсключения = ТекстИсключения + Прав(ТекстОтвета, ПоловинаМаксимальнойДлиныТекстаИсключения);
КонецЕсли;
ВызватьИсключение ТекстИсключения;
ВызватьИсключение КакИсключение(Ответ, НСтр("ru = 'Ошибка при десериализации JSON.'"));
КонецПопытки;

КонецФункции

// Возвращает ответ сервера в виде текста.
//
// Параметры:
// Ответ - См. ВызватьМетод
// Ответ - См. НовыйОтвет
// Кодировка - Строка, КодировкаТекста - определяет кодировку текста.
// Если значение не задано, то кодировка извлекается из Ответ.Кодировка.
//
Expand Down Expand Up @@ -540,7 +564,7 @@
// Возвращает ответ сервера в двоичных данных.
//
// Параметры:
// Ответ - См. ВызватьМетод
// Ответ - См. НовыйОтвет
//
// Возвращаемое значение:
// Строка - ответ сервера в виде двоичных данных.
Expand All @@ -554,7 +578,7 @@
// Возвращает ответ сервера в XDTO.
//
// Параметры:
// Ответ - См. ВызватьМетод
// Ответ - См. НовыйОтвет
// ПараметрыЧтенияXML - ПараметрыЧтенияXML - Параметры чтения, которые будут использованы при чтении данных XML
// Подробнее см. в синтакс помощнике метод ЧтениеXML.ОткрытьПоток
// НаборСхемXML - НаборСхемXML - Набор схем XML, используемых при проверке читаемого документа XML.
Expand All @@ -572,22 +596,68 @@
НаборСхемXML = Неопределено,
Кодировка = Неопределено) Экспорт

ДвоичныеДанные = РаспаковатьОтвет(Ответ);
ПотокДляЧтения = ДвоичныеДанные.ОткрытьПотокДляЧтения();

Если Не ЗначениеЗаполнено(Кодировка) Тогда
Кодировка = Ответ.Кодировка;
КонецЕсли;

ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьПоток(ПотокДляЧтения, ПараметрыЧтенияXML, НаборСхемXML, Кодировка);

ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
Попытка
ДвоичныеДанные = РаспаковатьОтвет(Ответ);

ПотокДляЧтения = ДвоичныеДанные.ОткрытьПотокДляЧтения();

Если Не ЗначениеЗаполнено(Кодировка) Тогда
Кодировка = Ответ.Кодировка;
КонецЕсли;

ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьПоток(ПотокДляЧтения, ПараметрыЧтенияXML, НаборСхемXML, Кодировка);

ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
Исключение
ВызватьИсключение КакИсключение(Ответ, НСтр("ru = 'Ошибка при десериализации XDTO.'"));
КонецПопытки;

Возврат ОбъектXDTO;

КонецФункции

// Возвращает ответ сервера в виде текста предназначенного для использования в ВызватьИсключение.
//
// Параметры:
// Ответ - См. НовыйОтвет.
// ТекстДляПользователя - Строка - Текст пояснения причины для пользователя.
//
// Возвращаемое значение:
// Строка - ответ сервера в виде текста исключения.
//
Функция КакИсключение(Ответ, Знач ТекстДляПользователя = Неопределено) Экспорт

ТекстИсключения = СтрШаблон(
НСтр("ru = 'HTTP %1 %2
|%3'"),
Ответ.Метод,
Ответ.URL,
ПредставлениеКодаСостоянияHTTP(Ответ.КодСостояния)
);

ТелоОтвета = ВырезатьТекст(КакТекст(Ответ));

Если Не ПустаяСтрока(ТелоОтвета) Тогда
ТекстИсключения = ТекстИсключения + Символы.ПС + СтрШаблон(
НСтр("ru = 'Тело ответа:
|%1'"),
ТелоОтвета);
КонецЕсли;

Если Ответ.Ошибки.Количество() Тогда
ТекстИсключения = ТекстИсключения + Символы.ПС + Символы.ПС
+ СтрСоединить(Ответ.Ошибки, Символы.ПС + Символы.ПС);
КонецЕсли;

Если Не ПустаяСтрока(ТекстДляПользователя) Тогда
ТекстИсключения = ТекстДляПользователя + Символы.ПС + Символы.ПС + ТекстИсключения;
КонецЕсли;

Возврат ТекстИсключения;

КонецФункции

#КонецОбласти

#Область ВспомогательныеФункции
Expand Down Expand Up @@ -917,7 +987,7 @@
КонецЦикла;

Если ОписаниеКодаСостояния = Неопределено Тогда
ВызватьИсключение(СтрШаблон(НСтр("ru = 'Неизвестный код состояния HTTP: %1'"), КодСостояния));
Возврат СтрШаблон(НСтр("ru = '%1: Неизвестный код состояния HTTP'"), КодСостояния);
Иначе
Возврат СтрШаблон("%1: %2", ОписаниеКодаСостояния.Код, ОписаниеКодаСостояния.Описание);
КонецЕсли;
Expand Down Expand Up @@ -1355,11 +1425,23 @@

Повтор = 0;
Длительность = 0;
Ошибки = Новый Массив;

Пока Истина Цикл
Попытка
Ответ = ОтправитьHTTPЗапрос(Сессия, ПодготовленныйЗапрос, Настройки);
Исключение
ОшибкаВыполненияЗапроса = ИнформацияОбОшибке();

ТекстОшибки = СтрШаблон(
НСтр("ru = 'HTTP %1 %2
|Network error:
|%3'"),
ПодготовленныйЗапрос.Метод,
ПодготовленныйЗапрос.URL,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())
);
Ошибки.Добавить(ТекстОшибки);
КонецПопытки;

Повтор = Повтор + 1;
Expand All @@ -1380,6 +1462,11 @@
Иначе
ЗаголовокRetryAfter = ЗначениеЗаголовка("retry-after", Ответ.Заголовки);
КонецЕсли;

Если ОшибкаВыполненияЗапроса <> Неопределено Тогда
Ошибки.Добавить(КакИсключение(Ответ));
КонецЕсли;

ДлительностьПриостановки = РассчитатьДлительностьПриостановки(
Повтор,
Настройки.КоэффициентЭкспоненциальнойЗадержки,
Expand All @@ -1397,17 +1484,18 @@
ЗаголовокContentType = "";
КонецЕсли;

ПодготовленныйОтвет = Новый Структура;
ПодготовленныйОтвет.Вставить("ВремяВыполнения", ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало);
ПодготовленныйОтвет.Вставить("Cookies", ИзвлечьCookies(Ответ.Заголовки, ПодготовленныйЗапрос.URL));
ПодготовленныйОтвет.Вставить("Заголовки", Ответ.Заголовки);
ПодготовленныйОтвет.Вставить("ЭтоПостоянныйРедирект", ЭтоПостоянныйРедирект(Ответ.КодСостояния, Ответ.Заголовки));
ПодготовленныйОтвет.Вставить("ЭтоРедирект", ЭтоРедирект(Ответ.КодСостояния, Ответ.Заголовки));
ПодготовленныйОтвет.Вставить("Кодировка", КодировкаИзЗаголовка(ЗаголовокContentType));
ПодготовленныйОтвет.Вставить("Тело", Ответ.ПолучитьТелоКакДвоичныеДанные());
ПодготовленныйОтвет.Вставить("КодСостояния", Ответ.КодСостояния);
ПодготовленныйОтвет.Вставить("URL", ПодготовленныйЗапрос.URL);

ПодготовленныйОтвет = НовыйОтвет();
ПодготовленныйОтвет.Метод = ПодготовленныйЗапрос.Метод;
ПодготовленныйОтвет.URL = ПодготовленныйЗапрос.URL;
ПодготовленныйОтвет.КодСостояния = Ответ.КодСостояния;
ПодготовленныйОтвет.Заголовки = Ответ.Заголовки;
ПодготовленныйОтвет.Тело = Ответ.ПолучитьТелоКакДвоичныеДанные();
ПодготовленныйОтвет.Кодировка = КодировкаИзЗаголовка(ЗаголовокContentType);
ПодготовленныйОтвет.ВремяВыполнения = ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало;
ПодготовленныйОтвет.ЭтоПостоянныйРедирект = ЭтоПостоянныйРедирект(Ответ.КодСостояния, Ответ.Заголовки);
ПодготовленныйОтвет.ЭтоРедирект = ЭтоРедирект(Ответ.КодСостояния, Ответ.Заголовки);
ПодготовленныйОтвет.Cookies = ИзвлечьCookies(Ответ.Заголовки, ПодготовленныйЗапрос.URL);

Сессия.Cookies = ОбъединитьCookies(Сессия.Cookies, ПодготовленныйОтвет.Cookies);

Возврат ПодготовленныйОтвет;
Expand Down Expand Up @@ -3212,6 +3300,25 @@

КонецФункции

Функция ВырезатьТекст(Текст, МаксимальнаяДлинаТекста = 1000)

Если НайтиНедопустимыеСимволыXML(Текст) Тогда
Возврат НСтр("ru ='<Данные>'");
КонецЕсли;

Если СтрДлина(Текст) <= МаксимальнаяДлинаТекста Тогда
Результат = Текст;
Иначе
ПоловинаМаксимальнойДлиныТекста = МаксимальнаяДлинаТекста / 2;
Результат = Лев(Текст, ПоловинаМаксимальнойДлиныТекста);
Результат = Результат + Символы.ПС + "..." + Символы.ПС;
Результат = Результат + Прав(Текст, ПоловинаМаксимальнойДлиныТекста);
КонецЕсли;

Возврат Результат;

КонецФункции

#КонецОбласти

#КонецОбласти
7 changes: 3 additions & 4 deletions src/ru/DataProcessors/Тесты/Ext/ObjectModule.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -949,10 +949,9 @@
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");

ПодготовленныйОтвет = Новый Структура;
ПодготовленныйОтвет.Вставить("Тело", ДвоичныеДанныеОтвет);
ПодготовленныйОтвет.Вставить("Заголовки", Заголовки);
ПодготовленныйОтвет.Вставить("Кодировка", "UTF-8");
ПодготовленныйОтвет = КоннекторHTTP.НовыйОтвет();
ПодготовленныйОтвет.Тело = ДвоичныеДанныеОтвет;
ПодготовленныйОтвет.Заголовки = Заголовки;

ОтветXDTO = КоннекторHTTP.КакXDTO(ПодготовленныйОтвет);

Expand Down

0 comments on commit 2b24c16

Please sign in to comment.