diff --git "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP/Ext/Module.bsl" "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP/Ext/Module.bsl"
index 411cf30..6df1ece 100644
--- "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP/Ext/Module.bsl"
+++ "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP/Ext/Module.bsl"
@@ -54,6 +54,15 @@
Возврат ТекущаяУниверсальнаяДата();
КонецФункции
+// Возвращает текущий Unix Timestamp
+//
+// Возвращаемое значение:
+// Число - количество секунд, прошедших с 01.01.1970 по текущее время UTC
+//
+Функция ВременнаяМеткаUnix() Экспорт
+ Возврат ТекущаяУниверсальнаяДата() - КлиентHTTPПовтИсп.ЭпохаUnix();
+КонецФункции
+
// Возвращает раскодированный URI в URL кодировке
//
// Параметры:
@@ -73,7 +82,7 @@
// КонтекстВыполненияАдресВХ - Строка - адрес контекста выполнения запроса во временном хранилище
//
// Возвращаемое значение:
-// Строка - значение заголовка Digest-авторизации
+// Строка - значение заголовка Digest-аутентификации
//
Функция ЗаголовокDigest(Знач Конфигурация, Знач КонтекстВыполненияАдресВХ) Экспорт
КонтекстВыполнения = ПолучитьИзВременногоХранилища(КонтекстВыполненияАдресВХ);
@@ -81,7 +90,7 @@
Параметры = Конфигурация.ДополнительныеПараметры.Сессия.ПараметрыDigest;
Аутентификация = Конфигурация.ДополнительныеПараметры.Аутентификация;
- АдресРесурсаСПараметрами = Конфигурация.ДанныеURI.АдресРесурса + Конфигурация.Параметры;
+ ПутьСПараметрами = Конфигурация.ДанныеURI.Путь + Конфигурация.ПараметрыСтрокой;
АлгоритмХеширования = НРег(Параметры.algorithm);
УникальныйКлючКлиента = Лев(СтрЗаменить(НРег(Новый УникальныйИдентификатор), "-", ""), 16);
@@ -98,8 +107,8 @@
A2 = ?(
КачествоЗащиты = "auth-int",
- СтрШаблон("%1:%2:%3", КонтекстВыполнения.Метод, АдресРесурсаСПараметрами, ХешСтрока(КонтекстВыполнения.Данные, АлгоритмХеширования)),
- СтрШаблон("%1:%2", КонтекстВыполнения.Метод, АдресРесурсаСПараметрами)
+ СтрШаблон("%1:%2:%3", КонтекстВыполнения.Метод, ПутьСПараметрами, ХешСтрока(КонтекстВыполнения.Данные, АлгоритмХеширования)),
+ СтрШаблон("%1:%2", КонтекстВыполнения.Метод, ПутьСПараметрами)
);
HA2 = ХешСтрока(A2, АлгоритмХеширования);
@@ -134,7 +143,7 @@
Конфигурация.ДополнительныеПараметры.Аутентификация.Пользователь,
Параметры.realm,
Параметры.nonce,
- АдресРесурсаСПараметрами,
+ ПутьСПараметрами,
Ответ
)
);
@@ -152,7 +161,219 @@
Возврат СтрСоединить(фРезультат);
КонецФункции
-// Возвращает коллекцию раскодированных строк
+// Возвращает заголовки AWS4-аутентификации
+//
+// Параметры:
+// Метод - Строка - имя HTTP-метода
+// Конфигурация - Структура - конфигурация выполнения запроса
+// ДанныеАдресВХ - Строка - адрес данных тела запроса во временном хранилище
+//
+// Возвращаемое значение:
+// Массив - заголовки AWS4-аутентификации
+//
+Функция ЗаголовкиAWS4(Знач Метод, Знач Конфигурация, Знач ДанныеАдресВХ) Экспорт
+ фРезультат = Новый Массив;
+
+ Данные = ПолучитьИзВременногоХранилища(ДанныеАдресВХ);
+ УдалитьИзВременногоХранилища(ДанныеАдресВХ);
+
+ ЗаголовокAmzContent = ХешСтрока(Данные, ХешФункция.SHA256);
+
+ СпецификацияЗапроса = "aws4_request";
+ АлгоритмШифрования = "AWS4-HMAC-SHA256";
+ Аутентификация = Конфигурация.ДополнительныеПараметры.АвторизоватьсяAWS4;
+ Регион = ?(ПустаяСтрока(Аутентификация.Регион), КлиентHTTPПовтИсп.РегионAWSПоУмолчанию(), Аутентификация.Регион);
+ ТУД = ТекущаяУниверсальнаяДата();
+ ЗаголовокAmzDate = Формат(ТУД, "ДФ=yyyyMMddTHHmmssZ");
+ ДатаДействия = Формат(ТУД, "ДФ=yyyyMMdd");
+
+ фРезультат.Добавить(Новый Структура("Ключ, Значение", "X-Amz-Date", ЗаголовокAmzDate));
+ фРезультат.Добавить(Новый Структура("Ключ, Значение", "X-Amz-Content-Sha256", ЗаголовокAmzContent));
+
+ СписокЗаголовков = СписокЗаголовковAWS4(Конфигурация.Заголовки, фРезультат);
+ ПодписываемыеЗаголовки = ПодписываемыеЗаголовкиAWS4(СписокЗаголовков);
+
+ ЧастиСтроки = Новый Массив;
+ ЧастиСтроки.Добавить(Метод);
+ ЧастиСтроки.Добавить(Конфигурация.ДанныеURI.Путь);
+ ЧастиСтроки.Добавить(КаноническиеПараметрыAWS4(Конфигурация.Параметры));
+ ЧастиСтроки.Добавить(КаноническиеЗаголовкиAWS4(СписокЗаголовков));
+ ЧастиСтроки.Добавить(ПодписываемыеЗаголовки);
+ ЧастиСтроки.Добавить(ЗаголовокAmzContent);
+ КаноническийЗапрос = СтрСоединить(ЧастиСтроки, Символы.ПС);
+
+ ЧастиСтроки = Новый Массив;
+ ЧастиСтроки.Добавить(ДатаДействия);
+ ЧастиСтроки.Добавить(Регион);
+ ЧастиСтроки.Добавить(Аутентификация.Сервис);
+ ЧастиСтроки.Добавить(СпецификацияЗапроса);
+ ОбластьДействия = СтрСоединить(ЧастиСтроки, "/");
+
+ ЧастиСтроки = Новый Массив;
+ ЧастиСтроки.Добавить(АлгоритмШифрования);
+ ЧастиСтроки.Добавить(ЗаголовокAmzDate);
+ ЧастиСтроки.Добавить(ОбластьДействия);
+ ЧастиСтроки.Добавить(ХешСтрока(КаноническийЗапрос, ХешФункция.SHA256));
+ СтрокаДляПодписи = СтрСоединить(ЧастиСтроки, Символы.ПС);
+
+ Подпись = HMAC256(ПолучитьДвоичныеДанныеИзСтроки("AWS4" + Аутентификация.СекретныйКлюч), ПолучитьДвоичныеДанныеИзСтроки(ДатаДействия));
+ Подпись = HMAC256(Подпись, ПолучитьДвоичныеДанныеИзСтроки(Регион));
+ Подпись = HMAC256(Подпись, ПолучитьДвоичныеДанныеИзСтроки(Аутентификация.Сервис));
+ Подпись = HMAC256(Подпись, ПолучитьДвоичныеДанныеИзСтроки(СпецификацияЗапроса));
+ Подпись = НРег(ПолучитьHexСтрокуИзДвоичныхДанных(HMAC256(Подпись, ПолучитьДвоичныеДанныеИзСтроки(СтрокаДляПодписи))));
+
+ фРезультат.Добавить(Новый Структура(
+ "Ключ, Значение",
+ КлиентHTTPПовтИсп.ЗаголовокТипАутентификации(),
+ СтрШаблон(
+ "%1 Credential=%2/%3, SignedHeaders=%4, Signature=%5",
+ АлгоритмШифрования,
+ Аутентификация.КлючДоступа,
+ ОбластьДействия,
+ ПодписываемыеЗаголовки,
+ Подпись
+ )
+ ));
+
+ Возврат Новый ФиксированныйМассив(фРезультат);
+КонецФункции
+
+// Возвращает значение заголовка Hawk-аутентификации
+// Расчёт подписи содержимого тела запроса не обязателен для Hawk-аутентификации.
+//
+// Параметры:
+// Метод - Строка - имя HTTP-метода
+// Конфигурация - Структура - конфигурация выполнения запроса
+// ДанныеАдресВХ - Строка, Неопределено - адрес данных тела запроса во временном хранилище (необязательный)
+//
+// Возвращаемое значение:
+// Строка - значение заголовка Hawk-аутентификации
+//
+Функция ЗаголовокHawk(Знач Метод, Конфигурация, Знач ДанныеАдресВХ = Неопределено) Экспорт
+ фРезультат = Новый Массив;
+
+ ПодписьТела = "";
+ Если ДанныеАдресВХ <> Неопределено Тогда
+ Данные = ПолучитьИзВременногоХранилища(ДанныеАдресВХ);
+ УдалитьИзВременногоХранилища(ДанныеАдресВХ);
+
+ ПодписьТела = ПодписьТелаHawk(
+ Данные,
+ КлиентHTTPКлиентСервер.ТипMIMEИзЗаголовков(Конфигурация.Заголовки)
+ );
+ КонецЕсли;
+
+ Аутентификация = Конфигурация.ДополнительныеПараметры.АвторизоватьсяHawk;
+ ДополнительныеДанные = НормализованныеДополнительныеДанныеHawk(Аутентификация.Дополнение);
+ РазовоеСлово = НовоеРазовоеСлово();
+ ВременнаяМетка = XMLСтрока(ВременнаяМеткаUnix());
+
+ ЧастиСтроки = Новый Массив;
+ ЧастиСтроки.Добавить("hawk.1.header");
+ ЧастиСтроки.Добавить(ВременнаяМетка);
+ ЧастиСтроки.Добавить(РазовоеСлово);
+ ЧастиСтроки.Добавить(Метод);
+ ЧастиСтроки.Добавить(Конфигурация.ДанныеURI.Путь);
+ ЧастиСтроки.Добавить(НРег(Конфигурация.ДанныеURI.Сервер));
+ ЧастиСтроки.Добавить(XMLСтрока(Конфигурация.ДанныеURI.Порт));
+ ЧастиСтроки.Добавить(ПодписьТела);
+ ЧастиСтроки.Добавить(ДополнительныеДанные);
+
+ Если НЕ ПустаяСтрока(Аутентификация.ИдентификаторПриложения) Тогда
+ ЧастиСтроки.Добавить(Аутентификация.ИдентификаторПриложения);
+ ЧастиСтроки.Добавить(Аутентификация.Делегирование);
+ КонецЕсли;
+
+ ЧастиСтроки.Добавить("");
+
+ Подпись = Base64Строка(HMAC256(
+ ПолучитьДвоичныеДанныеИзСтроки(Аутентификация.Ключ),
+ ПолучитьДвоичныеДанныеИзСтроки(СтрСоединить(ЧастиСтроки, Символы.ПС))
+ ));
+
+ фРезультат.Добавить(СтрШаблон("Hawk id=""%1"", ts=""%2"", nonce=""%3""", Аутентификация.Идентификатор, ВременнаяМетка, РазовоеСлово));
+ Если ПодписьТела <> "" Тогда
+ фРезультат.Добавить(СтрШаблон("hash=""%1""", ПодписьТела));
+ КонецЕсли;
+ Если ДополнительныеДанные <> "" Тогда
+ фРезультат.Добавить(СтрШаблон("ext=""%1""", ДополнительныеДанные));
+ КонецЕсли;
+ фРезультат.Добавить(СтрШаблон("mac=""%1""", Подпись));
+ Если НЕ ПустаяСтрока(Аутентификация.ИдентификаторПриложения) Тогда
+ фРезультат.Добавить(СтрШаблон("app=""%1""", Аутентификация.ИдентификаторПриложения));
+ Если НЕ ПустаяСтрока(Аутентификация.Делегирование) Тогда
+ фРезультат.Добавить(СтрШаблон("dlg=""%1""", Аутентификация.Делегирование));
+ КонецЕсли;
+ КонецЕсли;
+
+ Аутентификация = Новый Структура(Аутентификация);
+ Аутентификация.Вставить("РазовоеСлово", РазовоеСлово);
+ Аутентификация.Вставить("ВременнаяМетка", ВременнаяМетка);
+
+ Конфигурация.ДополнительныеПараметры.АвторизоватьсяHawk = Новый ФиксированнаяСтруктура(Аутентификация);
+
+ Возврат СтрСоединить(фРезультат, ", ");
+КонецФункции
+
+// Возвращает результат валидации ответа сервера по указанному заголовку (Hawk аутентификация)
+// Если валидация прошла успешно, вернётся Истина.
+//
+// Параметры:
+// ЗначениеЗаголовка - Строка - значение заголовка ответа сервера с данными Hawk аутентификации
+// КонтекстHawk - Структура - данные Hawk аутентификации запроса
+// ДанныеАдресВХ - Строка - адрес данных тела ответа и MIME-типа во временном хранилище
+// ОписаниеОшибки - Строка - описание ошибки валидации ответа
+//
+// Возвращаемое значение:
+// Булево - результат валидации
+//
+Функция ОтветСЗаголовкомHawkКорректен(Знач ЗначениеЗаголовка, Знач КонтекстHawk, Знач ДанныеАдресВХ, ОписаниеОшибки) Экспорт
+ ДанныеСервера = ДанныеЗаголовкаОтветаHawk(ЗначениеЗаголовка);
+
+ ПодписьТела = "";
+ Если ДанныеСервера.ПодписьТела <> "" Тогда
+ Данные = ПолучитьИзВременногоХранилища(ДанныеАдресВХ);
+ ПодписьТела = ПодписьТелаHawk(Данные.Тело, Данные.ТипMIME);
+ КонецЕсли;
+ УдалитьИзВременногоХранилища(ДанныеАдресВХ);
+
+ Если ПодписьТела <> ДанныеСервера.ПодписьТела Тогда
+ ОписаниеОшибки = СтрШаблон("Не совпадают подписи тела ответа: рассчитана '%1', получена '%2'", ПодписьТела, ДанныеСервера.ПодписьТела);
+ Возврат Ложь;
+ КонецЕсли;
+
+ ЧастиСтроки = Новый Массив;
+ ЧастиСтроки.Добавить("hawk.1.response");
+ ЧастиСтроки.Добавить(КонтекстHawk.ВременнаяМетка);
+ ЧастиСтроки.Добавить(КонтекстHawk.РазовоеСлово);
+ ЧастиСтроки.Добавить(КонтекстHawk.Метод);
+ ЧастиСтроки.Добавить(КонтекстHawk.Путь);
+ ЧастиСтроки.Добавить(НРег(КонтекстHawk.Хост));
+ ЧастиСтроки.Добавить(XMLСтрока(КонтекстHawk.Порт));
+ ЧастиСтроки.Добавить(ПодписьТела);
+ ЧастиСтроки.Добавить(ДанныеСервера.Дополнение);
+
+ Если НЕ ПустаяСтрока(КонтекстHawk.ИдентификаторПриложения) Тогда
+ ЧастиСтроки.Добавить(КонтекстHawk.ИдентификаторПриложения);
+ ЧастиСтроки.Добавить(КонтекстHawk.Делегирование);
+ КонецЕсли;
+
+ ЧастиСтроки.Добавить("");
+
+ Подпись = Base64Строка(HMAC256(
+ ПолучитьДвоичныеДанныеИзСтроки(КонтекстHawk.Ключ),
+ ПолучитьДвоичныеДанныеИзСтроки(СтрСоединить(ЧастиСтроки, Символы.ПС))
+ ));
+
+ Если Подпись <> ДанныеСервера.Подпись Тогда
+ ОписаниеОшибки = СтрШаблон("Не совпадают подписи ответа: рассчитана '%1', получена '%2'", Подпись, ДанныеСервера.Подпись);
+ Возврат Ложь;
+ КонецЕсли;
+
+ Возврат Истина;
+КонецФункции
+
+// (УСТАРЕЛО) Возвращает коллекцию раскодированных строк
//
// Параметры:
// КоллекцияСтрок - Структура - коллекция строк для раскодирования (обрабатываются только значения)
@@ -175,7 +396,31 @@
Возврат фРезультат;
КонецФункции
-// Возвращает коллекцию кодированных строк
+// Возвращает множество раскодированных строк способом КодировкаURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для раскодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество раскодированных строк
+//
+Функция РаскодированныеСтрокиURL(Знач МножествоСтрок) Экспорт
+ Возврат РаскодированныеСтрокиСпособом(МножествоСтрок, СпособКодированияСтроки.КодировкаURL);
+КонецФункции
+
+// Возвращает множество раскодированных строк способом URLВКодировкеURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для раскодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество раскодированных строк
+//
+Функция РаскодированныеСтрокиURLвURL(Знач МножествоСтрок) Экспорт
+ Возврат РаскодированныеСтрокиСпособом(МножествоСтрок, СпособКодированияСтроки.URLВКодировкеURL);
+КонецФункции
+
+// (УСТАРЕЛО) Возвращает коллекцию кодированных строк
//
// Параметры:
// КоллекцияСтрок - Структура - коллекция строк для кодирования (обрабатываются только значения)
@@ -198,6 +443,30 @@
Возврат фРезультат;
КонецФункции
+// Возвращает множество кодированных строк способом КодировкаURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для кодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество кодированных строк
+//
+Функция КодированныеСтрокиURL(Знач МножествоСтрок) Экспорт
+ Возврат КодированныеСтрокиСпособом(МножествоСтрок, СпособКодированияСтроки.КодировкаURL);
+КонецФункции
+
+// Возвращает множество кодированных строк способом URLВКодировкеURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для кодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество кодированных строк
+//
+Функция КодированныеСтрокиURLвURL(Знач МножествоСтрок) Экспорт
+ Возврат КодированныеСтрокиСпособом(МножествоСтрок, СпособКодированияСтроки.URLВКодировкеURL);
+КонецФункции
+
// Возвращает коллекцию раскодированных полей HTML-Формы
//
// Параметры:
@@ -374,8 +643,11 @@
// собирать значение печеньки пока не придёт знак (ТипТокена В {1, 2}) его записать
Действие.ЗаписатьЗначениеПеченьки = Ложь;
Действие.СобиратьЗначениеПеченьки = Истина;
- СостояниеПеченьки.Построитель.Добавить(СостояниеПеченьки.Объект.Значение + ЧастьОписанияПеченья(ОписанияПеченья.Исходное, СостояниеЧтения));
- СостояниеПеченьки.Построитель.Добавить(СостояниеЧтения.Токен.Токен);
+ ЧастиОписания = ЧастьОписанияПеченья(ОписанияПеченья.Исходное, СостояниеЧтения);
+ Если НЕ ПустаяСтрока(ЧастиОписания) Тогда
+ СостояниеПеченьки.Построитель.Добавить(СостояниеПеченьки.Объект.Значение + ЧастиОписания);
+ СостояниеПеченьки.Построитель.Добавить(СостояниеЧтения.Токен.Токен);
+ КонецЕсли;
СостояниеЧтения.Позиция = СостояниеЧтения.Токен.Позиция + 1;
ПереключитьСостояниеДКА(СостояниеДКА);
КонецПроцедуры
@@ -552,6 +824,10 @@
КонецПроцедуры
Функция ЧастьОписанияПеченья(Знач ОписаниеПеченьки, Знач СостояниеЧтения, Знач Смещение = 0)
+ Если СостояниеЧтения.Токен.Позиция - СостояниеЧтения.Позиция + Смещение < 1 Тогда
+ Возврат "";
+ КонецЕсли;
+
Возврат Сред(
ОписаниеПеченьки,
СостояниеЧтения.Позиция,
@@ -659,7 +935,7 @@
КонецФункции
Функция ХешСтрока(Знач Данные, Знач Алгоритм)
- ТипФункции = ТипХешФункции(Алгоритм);
+ ТипФункции = ?(ТипЗнч(Алгоритм) = Тип("ХешФункция"), Алгоритм, ТипХешФункции(Алгоритм));
Если ТипЗнч(Данные) = Тип("Строка") Тогда
Данные = ПолучитьДвоичныеДанныеИзСтроки(Данные, КлиентHTTPПовтИсп.КодировкаUTF8(), Ложь);
@@ -683,4 +959,209 @@
Возврат фРезультат;
КонецФункции
+
+Функция РаскодированныеСтрокиСпособом(Знач МножествоСтрок, Знач Способ)
+ фРезультат = Новый Соответствие;
+
+ Для Каждого КЗ Из МножествоСтрок Цикл
+ фРезультат.Вставить(КЗ.Ключ, РаскодироватьСтроку(КЗ.Ключ, Способ));
+ КонецЦикла;
+
+ Возврат фРезультат;
+КонецФункции
+
+Функция КодированныеСтрокиСпособом(Знач МножествоСтрок, Знач Способ)
+ фРезультат = Новый Соответствие;
+
+ Для Каждого КЗ Из МножествоСтрок Цикл
+ фРезультат.Вставить(КЗ.Ключ, КодироватьСтроку(КЗ.Ключ, Способ));
+ КонецЦикла;
+
+ Возврат фРезультат;
+КонецФункции
+
+Функция НовоеРазовоеСлово()
+ фРезультат = Новый Массив;
+
+ База = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ ДлинаБазы = СтрДлина(База);
+ ГСЧ = Новый ГенераторСлучайныхЧисел(13);
+ Для я = 1 По 32 Цикл
+ Позиция = ГСЧ.СлучайноеЧисло(1, ДлинаБазы);
+ фРезультат.Добавить(Сред(База, Позиция, 1));
+ КонецЦикла;
+
+ Возврат СтрСоединить(фРезультат);
+КонецФункции
+
+Функция HMAC256(Знач Ключ, Знач Данные)
+ АлгоритмХеширования = ХешФункция.SHA256;
+ РазмерБлока = 64;
+ Если Ключ.Размер() > РазмерБлока Тогда
+ Хеширование = Новый ХешированиеДанных(АлгоритмХеширования);
+ Хеширование.Добавить(Ключ);
+
+ Ключ = Хеширование.ХешСумма;
+ КонецЕсли;
+
+ ВнутренняяОснова = Новый БуферДвоичныхДанных(РазмерБлока);
+ ВнешняяОснова = Новый БуферДвоичныхДанных(РазмерБлока);
+ Для Позиция = 0 По РазмерБлока - 1 Цикл
+ ВнутренняяОснова.Установить(Позиция, 54); // 0x36
+ ВнешняяОснова.Установить(Позиция, 92); // 0x5C
+ КонецЦикла;
+
+ Буфер = Новый БуферДвоичныхДанных(РазмерБлока);
+ Буфер.Записать(0, ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Ключ));
+
+ ВнутреннийКлюч = Буфер.Скопировать();
+ ВнутреннийКлюч.ЗаписатьПобитовоеИсключительноеИли(0, ВнутренняяОснова);
+
+ ВнешнийКлюч = Буфер;
+ ВнешнийКлюч.ЗаписатьПобитовоеИсключительноеИли(0, ВнешняяОснова);
+
+ ВнутреннийХеш = Новый ХешированиеДанных(АлгоритмХеширования);
+ ВнешнийХеш = Новый ХешированиеДанных(АлгоритмХеширования);
+
+ ВнутреннийХеш.Добавить(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ВнутреннийКлюч));
+ ВнешнийХеш.Добавить(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ВнешнийКлюч));
+
+ Если ЗначениеЗаполнено(Данные) Тогда
+ ВнутреннийХеш.Добавить(Данные);
+ КонецЕсли;
+
+ ВнешнийХеш.Добавить(ВнутреннийХеш.ХешСумма);
+
+ Возврат ВнешнийХеш.ХешСумма;
+КонецФункции
+
+Функция КаноническиеПараметрыAWS4(Знач ПараметрыЗапроса)
+ фРезультат = Новый Массив;
+
+ СписокПараметров = Новый СписокЗначений;
+ Для Каждого Параметр Из ПараметрыЗапроса Цикл
+ Ключ = КодироватьСтроку(КлиентHTTPСлужебный.ФорматированноеИмяПараметраЗапроса(Параметр.Ключ), СпособКодированияСтроки.URLВКодировкеURL);
+ Если ПустаяСтрока(Ключ) Тогда
+ Продолжить;
+ КонецЕсли;
+ Если Параметр.Значение.Количество() = 0 Тогда
+ СписокПараметров.Добавить(Ключ);
+ Продолжить;
+ КонецЕсли;
+ Для Каждого Значение Из Параметр.Значение Цикл
+ СписокПараметров.Добавить(Ключ, КодироватьСтроку(КлиентHTTPСлужебный.ФорматированноеИмяПараметраЗапроса(Значение), СпособКодированияСтроки.URLВКодировкеURL));
+ КонецЦикла;
+ КонецЦикла;
+ СписокПараметров.СортироватьПоПредставлению();
+ СписокПараметров.СортироватьПоЗначению();
+
+ Для Каждого Параметр Из СписокПараметров Цикл
+ фРезультат.Добавить(Параметр.Значение + "=" + Параметр.Представление);
+ КонецЦикла;
+
+ Возврат СтрСоединить(фРезультат, "&");
+КонецФункции
+
+Функция СписокЗаголовковAWS4(Знач ЗаголовкиЗапроса, Знач ЗаголовкиAWS)
+ фРезультат = Новый СписокЗначений;
+
+ МножествоЗаголовков = Новый Соответствие;
+
+ Для Каждого Заголовок Из ЗаголовкиЗапроса Цикл
+ Ключ = НРег(Заголовок.Ключ);
+ Если Ключ = "host" ИЛИ СтрНачинаетсяС(Ключ, "x-amz-") Тогда
+ МножествоЗаголовков.Вставить(Ключ, Заголовок.Значение);
+ КонецЕсли;
+ КонецЦикла;
+ Для Каждого Заголовок Из ЗаголовкиAWS Цикл
+ МножествоЗаголовков.Вставить(НРег(Заголовок.Ключ), Заголовок.Значение);
+ КонецЦикла;
+
+ Для Каждого Заголовок Из МножествоЗаголовков Цикл
+ фРезультат.Добавить(Заголовок.Ключ, Заголовок.Значение);
+ КонецЦикла;
+ фРезультат.СортироватьПоЗначению(НаправлениеСортировки.Возр);
+
+ Возврат фРезультат;
+КонецФункции
+
+Функция КаноническиеЗаголовкиAWS4(Знач СписокЗаголовков)
+ фРезультат = Новый Массив;
+ Для Каждого Заголовок Из СписокЗаголовков Цикл
+ фРезультат.Добавить(СтрШаблон("%1:%2", Заголовок.Значение, Заголовок.Представление));
+ КонецЦикла;
+ фРезультат.Добавить("");
+
+ Возврат СтрСоединить(фРезультат, Символы.ПС);
+КонецФункции
+
+Функция ПодписываемыеЗаголовкиAWS4(Знач СписокЗаголовков)
+ фРезультат = Новый Массив;
+ Для Каждого Заголовок Из СписокЗаголовков Цикл
+ фРезультат.Добавить(Заголовок.Значение);
+ КонецЦикла;
+
+ Возврат СтрСоединить(фРезультат, ";");
+КонецФункции
+
+Функция НормализованныеДополнительныеДанныеHawk(Знач ДополнительныеДанные)
+ Возврат СтрЗаменить(СтрЗаменить(ДополнительныеДанные, "\", "\\"), Символы.ПС, "\n");
+КонецФункции
+
+Функция ПодписьТелаHawk(Знач Данные, Знач ТипКонтента)
+ Если Данные.Размер() = 0 ИЛИ НЕ ЗначениеЗаполнено(ТипКонтента) Тогда
+ Возврат "";
+ КонецЕсли;
+
+ Поток = Новый ПотокВПамяти;
+ Запись = Новый ЗаписьДанных(Поток);
+
+ Запись.ЗаписатьСимволы("hawk.1.payload");
+ Запись.ЗаписатьБайт(10); // символ '\n'
+ Запись.ЗаписатьСимволы(НРег(ТипКонтента));
+ Запись.ЗаписатьБайт(10);
+ Запись.Записать(Данные);
+ Запись.ЗаписатьБайт(10);
+
+ Хеширование = Новый ХешированиеДанных(ХешФункция.SHA256);
+ Хеширование.Добавить(Поток.ЗакрытьИПолучитьДвоичныеДанные());
+
+ Возврат Base64Строка(Хеширование.ХешСумма);
+КонецФункции
+
+Функция ДанныеЗаголовкаОтветаHawk(Знач ЗначениеЗаголовка)
+ фРезультат = Новый Структура("Подпись, ПодписьТела, Дополнение", "", "", "");
+
+ ПозицияНачала = СтрНайти(ЗначениеЗаголовка, " mac=""");
+ ПозицияОкончания = 0;
+ Если ПозицияНачала > 0 Тогда
+ ПозицияНачала = ПозицияНачала + 6;
+ ПозицияОкончания = СтрНайти(ЗначениеЗаголовка, """", , ПозицияНачала);
+ Если ПозицияОкончания > 0 Тогда
+ фРезультат.Подпись = Сред(ЗначениеЗаголовка, ПозицияНачала, ПозицияОкончания - ПозицияНачала);
+ КонецЕсли;
+ КонецЕсли;
+
+ ПозицияНачала = СтрНайти(ЗначениеЗаголовка, " hash=""");
+ ПозицияОкончания = 0;
+ Если ПозицияНачала > 0 Тогда
+ ПозицияНачала = ПозицияНачала + 7;
+ ПозицияОкончания = СтрНайти(ЗначениеЗаголовка, """", , ПозицияНачала);
+ Если ПозицияОкончания > 0 Тогда
+ фРезультат.ПодписьТела = Сред(ЗначениеЗаголовка, ПозицияНачала, ПозицияОкончания - ПозицияНачала);
+ КонецЕсли;
+ КонецЕсли;
+
+ ПозицияНачала = СтрНайти(ЗначениеЗаголовка, " ext=""");
+ ПозицияОкончания = 0;
+ Если ПозицияНачала > 0 Тогда
+ ПозицияНачала = ПозицияНачала + 6;
+ ПозицияОкончания = СтрНайти(ЗначениеЗаголовка, """", , ПозицияНачала);
+ Если ПозицияОкончания > 0 Тогда
+ фРезультат.Дополнение = Сред(ЗначениеЗаголовка, ПозицияНачала, ПозицияОкончания - ПозицияНачала);
+ КонецЕсли;
+ КонецЕсли;
+
+ Возврат фРезультат;
+КонецФункции
#КонецОбласти
diff --git "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\222\321\213\320\267\320\276\320\262\320\241\320\265\321\200\320\262\320\265\321\200\320\260/Ext/Module.bsl" "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\222\321\213\320\267\320\276\320\262\320\241\320\265\321\200\320\262\320\265\321\200\320\260/Ext/Module.bsl"
index 762dd87..c054f15 100644
--- "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\222\321\213\320\267\320\276\320\262\320\241\320\265\321\200\320\262\320\265\321\200\320\260/Ext/Module.bsl"
+++ "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\222\321\213\320\267\320\276\320\262\320\241\320\265\321\200\320\262\320\265\321\200\320\260/Ext/Module.bsl"
@@ -22,6 +22,15 @@
Возврат КлиентHTTP.ТекущаяУниверсальнаяДатаНаСервере();
КонецФункции
+// Возвращает текущий Unix Timestamp
+//
+// Возвращаемое значение:
+// Число - количество секунд, прошедших с 01.01.1970 по текущее время UTC
+//
+Функция ВременнаяМеткаUnix() Экспорт
+ Возврат КлиентHTTP.ВременнаяМеткаUnix();
+КонецФункции
+
// Возвращает раскодированный URI
//
// Параметры:
@@ -47,6 +56,51 @@
Возврат КлиентHTTP.ЗаголовокDigest(Конфигурация, КонтекстВыполненияАдресВХ);
КонецФункции
+// Возвращает заголовки AWS4-аутентификации
+//
+// Параметры:
+// Метод - Строка - имя HTTP-метода
+// Конфигурация - Структура - конфигурация выполнения запроса
+// ДанныеАдресВХ - Строка - адрес данных тела запроса во временном хранилище
+//
+// Возвращаемое значение:
+// Массив - заголовки AWS4-авторизации
+//
+Функция ЗаголовкиAWS4(Знач Метод, Знач Конфигурация, Знач ДанныеАдресВХ) Экспорт
+ Возврат КлиентHTTP.ЗаголовкиAWS4(Метод, Конфигурация, ДанныеАдресВХ);
+КонецФункции
+
+// Возвращает значение заголовка Hawk-аутентификации
+// Расчёт подписи содержимого тела запроса не обязателен для Hawk-аутентификации.
+//
+// Параметры:
+// Метод - Строка - имя HTTP-метода
+// Конфигурация - Структура - конфигурация выполнения запроса
+// ДанныеАдресВХ - Строка, Неопределено - адрес данных тела запроса во временном хранилище (необязательный)
+//
+// Возвращаемое значение:
+// Строка - значение заголовка Hawk-аутентификации
+//
+Функция ЗаголовокHawk(Знач Метод, Конфигурация, Знач ДанныеАдресВХ = Неопределено) Экспорт
+ Возврат КлиентHTTP.ЗаголовокHawk(Метод, Конфигурация, ДанныеАдресВХ);
+КонецФункции
+
+// Возвращает результат валидации ответа сервера по указанному заголовку (Hawk аутентификация)
+// Если валидация прошла успешно, вернётся Истина.
+//
+// Параметры:
+// ЗначениеЗаголовка - Строка - значение заголовка ответа сервера с данными Hawk аутентификации
+// КонтекстHawk - Структура - данные Hawk аутентификации запроса
+// ДанныеАдресВХ - Строка - адрес данных тела ответа и MIME-типа во временном хранилище
+// ОписаниеОшибки - Строка - описание ошибки валидации ответа
+//
+// Возвращаемое значение:
+// Булево - результат валидации
+//
+Функция ОтветСЗаголовкомHawkКорректен(Знач ЗначениеЗаголовка, Знач КонтекстHawk, Знач ДанныеАдресВХ, ОписаниеОшибки) Экспорт
+ Возврат КлиентHTTP.ОтветСЗаголовкомHawkКорректен(ЗначениеЗаголовка, КонтекстHawk, ДанныеАдресВХ, ОписаниеОшибки);
+КонецФункции
+
// Добавляет запись ошибки в журнал регистрации
//
// Параметры:
@@ -58,7 +112,7 @@
КлиентHTTP.ДобавитьЗаписьОшибкиВЖурналРегистрации(Данные, Комментарий, СобытиеВТранзакции);
КонецПроцедуры
-// Возвращает коллекцию раскодированных строк
+// (УСТАРЕЛО) Возвращает коллекцию раскодированных строк
//
// Параметры:
// КоллекцияСтрок - Структура - коллекция строк для раскодирования (обрабатываются только значения)
@@ -71,7 +125,31 @@
Возврат КлиентHTTP.РаскодированныеСтроки(КоллекцияСтрок, Способ);
КонецФункции
-// Возвращает коллекцию кодированных строк
+// Возвращает множество раскодированных строк способом КодировкаURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для раскодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество раскодированных строк
+//
+Функция РаскодированныеСтрокиURL(Знач МножествоСтрок) Экспорт
+ Возврат КлиентHTTP.РаскодированныеСтрокиURL(МножествоСтрок);
+КонецФункции
+
+// Возвращает множество раскодированных строк способом URLВКодировкеURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для раскодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество раскодированных строк
+//
+Функция РаскодированныеСтрокиURLвURL(Знач МножествоСтрок) Экспорт
+ Возврат КлиентHTTP.РаскодированныеСтрокиURLвURL(МножествоСтрок);
+КонецФункции
+
+// (УСТАРЕЛО) Возвращает коллекцию кодированных строк
//
// Параметры:
// КоллекцияСтрок - Структура - коллекция строк для кодирования (обрабатываются только значения)
@@ -84,6 +162,30 @@
Возврат КлиентHTTP.ЗакодированныеСтроки(КоллекцияСтрок, Способ);
КонецФункции
+// Возвращает множество кодированных строк способом КодировкаURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для кодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество кодированных строк
+//
+Функция КодированныеСтрокиURL(Знач МножествоСтрок) Экспорт
+ Возврат КлиентHTTP.КодированныеСтрокиURL(МножествоСтрок);
+КонецФункции
+
+// Возвращает множество кодированных строк способом URLВКодировкеURL
+//
+// Параметры:
+// МножествоСтрок - Соответствие - множество строк для кодирования
+//
+// Возвращаемое значение:
+// Соответствие - множество кодированных строк
+//
+Функция КодированныеСтрокиURLвURL(Знач МножествоСтрок) Экспорт
+ Возврат КлиентHTTP.КодированныеСтрокиURLвURL(МножествоСтрок);
+КонецФункции
+
// Возвращает коллекцию раскодированных полей HTML-Формы
//
// Параметры:
diff --git "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\232\320\273\320\270\320\265\320\275\321\202\320\241\320\265\321\200\320\262\320\265\321\200/Ext/Module.bsl" "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\232\320\273\320\270\320\265\320\275\321\202\320\241\320\265\321\200\320\262\320\265\321\200/Ext/Module.bsl"
index c6714c2..236ab4b 100644
--- "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\232\320\273\320\270\320\265\320\275\321\202\320\241\320\265\321\200\320\262\320\265\321\200/Ext/Module.bsl"
+++ "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\232\320\273\320\270\320\265\320\275\321\202\320\241\320\265\321\200\320\262\320\265\321\200/Ext/Module.bsl"
@@ -17,7 +17,7 @@
// * ИмяФайлаТела - Строка, Неопределено - имя файла, в который было записано тело ответа
//
Функция Получить(Знач ИдентификаторРесурса, Знач ПараметрыЗапроса = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
- Возврат ВыполнитьЗапросHTTP(
+ Возврат ВыполненныйЗапросHTTP(
КлиентHTTPПовтИсп.МетодGET(),
КонфигурацияЗапроса(ИдентификаторРесурса, ПараметрыЗапроса, ДополнительныеПараметры)
);
@@ -38,7 +38,7 @@
// * ИмяФайлаТела - Строка, Неопределено - имя файла, в который было записано тело ответа
//
Функция ПолучитьЗаголовки(Знач ИдентификаторРесурса, Знач ПараметрыЗапроса = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
- Возврат ВыполнитьЗапросHTTP(
+ Возврат ВыполненныйЗапросHTTP(
КлиентHTTPПовтИсп.МетодHEAD(),
КонфигурацияЗапроса(ИдентификаторРесурса, ПараметрыЗапроса, ДополнительныеПараметры)
);
@@ -64,7 +64,7 @@
ДобавитьРазмерДанныхВЗаголовкиЗапроса(Конфигурация.Заголовки, Конфигурация.ДополнительныеПараметры, Данные);
- Возврат ВыполнитьЗапросHTTP(КлиентHTTPПовтИсп.МетодPOST(), Конфигурация, Данные);
+ Возврат ВыполненныйЗапросHTTP(КлиентHTTPПовтИсп.МетодPOST(), Конфигурация, Данные);
КонецФункции
// Реализация PUT
@@ -87,7 +87,7 @@
ДобавитьРазмерДанныхВЗаголовкиЗапроса(Конфигурация.Заголовки, Конфигурация.ДополнительныеПараметры, Данные);
- Возврат ВыполнитьЗапросHTTP(КлиентHTTPПовтИсп.МетодPUT(), Конфигурация, Данные);
+ Возврат ВыполненныйЗапросHTTP(КлиентHTTPПовтИсп.МетодPUT(), Конфигурация, Данные);
КонецФункции
// Реализация PATCH
@@ -110,7 +110,7 @@
ДобавитьРазмерДанныхВЗаголовкиЗапроса(Конфигурация.Заголовки, Конфигурация.ДополнительныеПараметры, Данные);
- Возврат ВыполнитьЗапросHTTP(КлиентHTTPПовтИсп.МетодPATCH(), Конфигурация, Данные);
+ Возврат ВыполненныйЗапросHTTP(КлиентHTTPПовтИсп.МетодPATCH(), Конфигурация, Данные);
КонецФункции
// Реализация DELETE
@@ -136,7 +136,7 @@
ДобавитьРазмерДанныхВЗаголовкиЗапроса(Конфигурация.Заголовки, Конфигурация.ДополнительныеПараметры, Данные);
КонецЕсли;
- Возврат ВыполнитьЗапросHTTP(КлиентHTTPПовтИсп.МетодDELETE(), Конфигурация, Данные);
+ Возврат ВыполненныйЗапросHTTP(КлиентHTTPПовтИсп.МетодDELETE(), Конфигурация, ПолучитьДвоичныеДанныеИзСтроки(Данные, КодировкаИзДопПараметров(Конфигурация.ДополнительныеПараметры)));
КонецФункции
#Область ДЕКОРАТОРЫ
@@ -192,7 +192,7 @@
//
Функция ОтправитьФайл(Знач ИдентификаторРесурса, Знач Данные, ДополнительныеПараметры = Неопределено, Знач ПараметрыЗапроса = Неопределено) Экспорт
Если НЕ Данные.Существует() Тогда
- ВызватьИсключение СтрШаблон("Файл %1 не существует", Данные.ПолноеИмя);
+ ВызватьИсключение СтрШаблон("Файл не обнаружен '%1'", Данные.ПолноеИмя);
КонецЕсли;
Если ДополнительныеПараметры = Неопределено Тогда
@@ -359,7 +359,7 @@
//
Функция ЗаписатьФайл(Знач ИдентификаторРесурса, Знач Данные, ДополнительныеПараметры = Неопределено, Знач ПараметрыЗапроса = Неопределено) Экспорт
Если НЕ Данные.Существует() Тогда
- ВызватьИсключение СтрШаблон("Файл %1 не существует", Данные.ПолноеИмя);
+ ВызватьИсключение СтрШаблон("Файл не обнаружен '%1'", Данные.ПолноеИмя);
КонецЕсли;
Если ДополнительныеПараметры = Неопределено Тогда
@@ -430,7 +430,7 @@
//
Функция ИзменитьФайл(Знач ИдентификаторРесурса, Знач Данные, ДополнительныеПараметры = Неопределено, Знач ПараметрыЗапроса = Неопределено) Экспорт
Если НЕ Данные.Существует() Тогда
- ВызватьИсключение СтрШаблон("Файл %1 не существует", Данные.ПолноеИмя);
+ ВызватьИсключение СтрШаблон("Файл не обнаружен '%1'", Данные.ПолноеИмя);
КонецЕсли;
Если ДополнительныеПараметры = Неопределено Тогда
@@ -602,6 +602,20 @@
Возврат КлиентHTTPКлиентСервер;
КонецФункции
+// Отмена требования попытки преобразования тела полученного ответа
+//
+// Параметры:
+// ДополнительныеПараметры - Структура - конфигурация выполнения запроса
+//
+// Возвращаемое значение:
+// ОбщийМодуль.КлиентHTTPКлиентСервер - модуль вызова функции
+//
+Функция ТелоОтветаКакДвоичныеДанные(ДополнительныеПараметры) Экспорт
+ ДополнительныеПараметры.Удалить("ПрочитатьТелоОтветаКак");
+
+ Возврат КлиентHTTPКлиентСервер;
+КонецФункции
+
// Требование попытки преобразования тела полученного ответа в текст
//
// Параметры:
@@ -758,6 +772,30 @@
Возврат КлиентHTTPКлиентСервер;
КонецФункции
+// Требование принудительно переключаться на метод GET для кодов перенаправления 301 и 302
+//
+// Параметры:
+// ДополнительныеПараметры - Структура - конфигурация выполнения запроса
+// КакGET - Булево - установить переключение на GET (необязательный)
+//
+// Возвращаемое значение:
+// ОбщийМодуль.КлиентHTTPКлиентСервер - модуль вызова функции
+//
+Функция ПеренаправленияКакGET(ДополнительныеПараметры, Знач КакGET = Истина) Экспорт
+ СессияАктивирована = ДополнительныеПараметры.Свойство("Сессия");
+ Если КакGET Тогда
+ Если НЕ СессияАктивирована Тогда
+ ИспользоватьСессию(ДополнительныеПараметры);
+ КонецЕсли;
+
+ ДополнительныеПараметры.Сессия.Вставить("ПеренаправлениеКакGET");
+ ИначеЕсли СессияАктивирована Тогда
+ ДополнительныеПараметры.Сессия.Удалить("ПеренаправлениеКакGET");
+ КонецЕсли;
+
+ Возврат КлиентHTTPКлиентСервер;
+КонецФункции
+
// Установка Basic-авторизации
//
// Параметры:
@@ -819,7 +857,65 @@
// ОбщийМодуль.КлиентHTTPКлиентСервер - модуль вызова функции
//
Функция УстановитьBearerАвторизацию(ДополнительныеПараметры, Знач Токен) Экспорт
- ДополнительныеПараметры.Вставить("Аутентификация", ОбъектАутентификации("Bearer", Токен, ""));
+ ДополнительныеПараметры.Вставить("Аутентификация", ОбъектАутентификацииBearer(Токен));
+
+ Возврат КлиентHTTPКлиентСервер;
+КонецФункции
+
+// Установка AWS4-авторизации
+//
+// Параметры:
+// ДополнительныеПараметры - Структура - конфигурация выполнения запроса
+// КлючДоступа - Строка - AWS ключ доступа
+// СекретныйКлюч - Строка - AWS секретный ключ
+// Регион - Строка - AWS регион получателя запроса (необязательный)
+// Сервис - Строка - AWS сервис получателя запроса (необязательный)
+//
+// Возвращаемое значение:
+// ОбщийМодуль.КлиентHTTPКлиентСервер - модуль вызова функции
+//
+Функция УстановитьAWS4Авторизацию(ДополнительныеПараметры, Знач КлючДоступа, Знач СекретныйКлюч, Знач Регион = "", Знач Сервис = "") Экспорт
+ ДополнительныеПараметры.Вставить(
+ "Аутентификация",
+ ОбъектАутентификацииAWS4(КлючДоступа, СекретныйКлюч, СокрЛП(Регион), СокрЛП(Сервис))
+ );
+
+ Возврат КлиентHTTPКлиентСервер;
+КонецФункции
+
+// Установка Hawk-авторизации
+//
+// Параметры:
+// ДополнительныеПараметры - Структура - конфигурация выполнения запроса
+// Идентификатор - Строка - ID аутентификации
+// Ключ - Строка - секретный ключ
+// Дополнение - Строка - (ext) специфические данные клиента (необязательный)
+// ИдентификаторПриложения - Строка - (app) идентификатор приложения (необязательный)
+// Делегирование - Строка - (dlg) выданный идентификатор приложения (необязательный)
+//
+// Возвращаемое значение:
+// ОбщийМодуль.КлиентHTTPКлиентСервер - модуль вызова функции
+//
+Функция УстановитьHawkАвторизацию(ДополнительныеПараметры, Знач Идентификатор, Знач Ключ, Знач Дополнение = "", Знач ИдентификаторПриложения = "", Знач Делегирование = "") Экспорт
+ ДополнительныеПараметры.Вставить(
+ "Аутентификация",
+ ОбъектАутентификацииHawk(Идентификатор, Ключ, СокрЛП(Дополнение), СокрЛП(ИдентификаторПриложения), СокрЛП(Делегирование))
+ );
+
+ Возврат КлиентHTTPКлиентСервер;
+КонецФункции
+
+// Установка пользовательского значения заголовка "User-Agent"
+//
+// Параметры:
+// ДополнительныеПараметры - Структура - конфигурация выполнения запроса
+// АгентПользователя - Строка - значение для заголовка User-Agent
+//
+// Возвращаемое значение:
+// ОбщийМодуль.КлиентHTTPКлиентСервер - модуль вызова функции
+//
+Функция УстановитьАгентаПользователя(ДополнительныеПараметры, Знач АгентПользователя) Экспорт
+ ДополнительныеПараметры.Вставить("АгентПользователя", СокрЛП(АгентПользователя));
Возврат КлиентHTTPКлиентСервер;
КонецФункции
@@ -1157,18 +1253,38 @@
Функция ПараметрыЗапросаСтрокой(Знач Параметры) Экспорт
фРезультат = Новый Массив;
+ ПараметрыИдентификатора = Новый Массив;
+ МножествоСтрок = Новый Соответствие;
Для Каждого КЗ Из Параметры Цикл
- ИмяПараметра = ФорматированноеИмяПараметраЗапроса(КЗ.Ключ);
- Если ПустаяСтрока(ИмяПараметра) Тогда
+ Параметр = Новый Структура("Ключ, Значение", КлиентHTTPСлужебный.ФорматированноеИмяПараметраЗапроса(КЗ.Ключ), "");
+ Если ПустаяСтрока(Параметр.Ключ) Тогда
+ Продолжить;
+ КонецЕсли;
+ МножествоСтрок.Вставить(Параметр.Ключ);
+ Если КЗ.Значение.Количество() = 0 Тогда
+ ПараметрыИдентификатора.Добавить(Параметр);
Продолжить;
КонецЕсли;
Для Каждого ЗначениеПараметра Из КЗ.Значение Цикл
- ФЗП = СокрЛП(ФорматированноеЗначениеПараметраЗапроса(ЗначениеПараметра));
- фРезультат.Добавить(ИмяПараметра + ?(ФЗП = "", "", "=") + ФЗП);
+ Параметр.Значение = КлиентHTTPСлужебный.ФорматированноеЗначениеПараметраЗапроса(ЗначениеПараметра);
+ Если Параметр.Значение <> "" Тогда
+ МножествоСтрок.Вставить(Параметр.Значение);
+ КонецЕсли;
+
+ ПараметрыИдентификатора.Добавить(Параметр);
КонецЦикла;
КонецЦикла;
+ МножествоСтрок = КлиентHTTPВызовСервера.КодированныеСтрокиURLвURL(МножествоСтрок);
+
+ Для Каждого Параметр Из ПараметрыИдентификатора Цикл
+ ИмяПараметра = МножествоСтрок.Получить(Параметр.Ключ);
+ ЗначениеПараметра = МножествоСтрок.Получить(Параметр.Значение);
+
+ фРезультат.Добавить(ИмяПараметра + ?(ЗначениеПараметра = "", "", "=") + ЗначениеПараметра);
+ КонецЦикла;
+
Возврат ?(фРезультат.Количество() = 0, "", "?" + СтрСоединить(фРезультат, "&"));
КонецФункции
@@ -1197,6 +1313,48 @@
ОбъединитьПеченье(КонфигурацияПриемник.Сессия.Печенье, КонфигурацияИсточник.Сессия.Печенье, Заменять);
КонецПроцедуры
+// Возвращает значение заголовка по имени
+//
+// Параметры:
+// ИмяЗаголовка - Строка - имя заголовка
+// Заголовки - Соответствие - коллекция заголовков
+//
+// Возвращаемое значение:
+// Строка, Неопределено - значение заголовка
+//
+Функция ЗначениеЗаголовка(Знач ИмяЗаголовка, Знач Заголовки) Экспорт
+ фРезультат = Неопределено;
+ ИмяЗаголовка = НРег(ИмяЗаголовка);
+
+ Для Каждого КЗ Из Заголовки Цикл
+ Если НРег(КЗ.Ключ) = ИмяЗаголовка Тогда
+ фРезультат = КЗ.Значение;
+ Прервать;
+ КонецЕсли;
+ КонецЦикла;
+
+ Возврат фРезультат;
+КонецФункции
+
+// Возвращает значение заголовка Cookie для идентификатора ресурса
+//
+// Параметры:
+// ИдентификаторРесурса - Строка, Структура - URI сервиса либо объект идентификатора ресурса
+// ДополнительныеПараметры - Структура - конфигурация выполнения запроса
+//
+// Возвращаемое значение:
+// Строка, Неопределено - значение заголовка Cookie
+//
+Функция ЗначениеЗаголовкаCookieРесурса(Знач ИдентификаторРесурса, Знач ДополнительныеПараметры) Экспорт
+ Если НЕ ДополнительныеПараметры.Свойство("Сессия") Тогда
+ Возврат Неопределено;
+ КонецЕсли;
+
+ ДанныеURI = СтруктураИдентификатораРесурса(ИдентификаторРесурса);
+
+ Возврат ЗначениеЗаголовкаCookie(ДанныеURI, ДополнительныеПараметры.Сессия);
+КонецФункции
+
// Возвращает MIME-тип из заголовков
//
// Параметры:
@@ -1206,7 +1364,7 @@
// Строка, Неопределено - значение заголовка Content-Type
//
Функция ТипMIMEИзЗаголовков(Знач Заголовки) Экспорт
- ТипКонтента = ЗначениеЗаголовка("Content-Type", Заголовки);
+ ТипКонтента = ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокТипКонтента(), Заголовки);
Если ТипКонтента = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
@@ -1225,7 +1383,7 @@
// Строка, Неопределено - значение charset заголовка Content-Type
//
Функция КодировкаИзЗаголовков(Знач Заголовки) Экспорт
- ТипКонтента = ЗначениеЗаголовка("Content-Type", Заголовки);
+ ТипКонтента = ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокТипКонтента(), Заголовки);
Если ТипКонтента = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
@@ -1234,30 +1392,74 @@
Возврат ?(ПозицияКодировки = 0, Неопределено, Сред(ТипКонтента, ПозицияКодировки + 8));
КонецФункции
+
+// Возвращает результат валидации ответа сервера по указанному заголовку (Hawk аутентификация)
+//
+// Параметры:
+// Ответ - Структура - объект ответа сервера
+// ИмяЗаголовка - Строка - имя заголовка ответа сервера с данными Hawk аутентификации
+// ОписаниеОшибки - Строка - описание ошибки валидации ответа
+//
+// Возвращаемое значение:
+// Строка, Неопределено - значение charset заголовка Content-Type
+//
+Функция ОтветСЗаголовкомHawkКорректен(Знач Ответ, Знач ИмяЗаголовка, ОписаниеОшибки) Экспорт
+ Если НЕ Ответ.КонтекстВыполнения.Свойство("АутентификацияHawk") Тогда
+ ОписаниеОшибки = "Отсутствует контекст Hawk аутентификации";
+ Возврат Ложь;
+ КонецЕсли;
+ Если Ответ.КодСостояния < 200 ИЛИ Ответ.КодСостояния > 299 Тогда
+ Возврат Истина;
+ КонецЕсли;
+ Если ТипЗнч(Ответ.Тело) <> Тип("ДвоичныеДанные") Тогда
+ ОписаниеОшибки = "Валидация доступна только для ответа с телом типа ДвоичныеДанные";
+ Возврат Ложь;
+ КонецЕсли;
+
+ ЗначениеЗаголовкаHawk = ЗначениеЗаголовка(ИмяЗаголовка, Ответ.Заголовки);
+ Если ЗначениеЗаголовкаHawk = Неопределено Тогда
+ ОписаниеОшибки = "В ответе отсутствует заголовок Hawk аутентификации";
+ Возврат Ложь;
+ КонецЕсли;
+
+ Данные = Новый Структура(
+ "Тело, ТипMIME",
+ Ответ.Тело,
+ ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокТипКонтента(), Ответ.Заголовки)
+ );
+
+ Возврат КлиентHTTPВызовСервера.ОтветСЗаголовкомHawkКорректен(
+ ЗначениеЗаголовкаHawk,
+ Ответ.КонтекстВыполнения.АутентификацияHawk,
+ ПоместитьВоВременноеХранилище(Данные, Новый УникальныйИдентификатор),
+ ОписаниеОшибки
+ );
+КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
-Функция ВыполнитьЗапросHTTP(Знач Метод, Знач Конфигурация, Знач Данные = Неопределено, Знач НомерПеренаправления = 0)
+Функция ВыполненныйЗапросHTTP(Знач Метод, Знач Конфигурация, Знач Данные = Неопределено, Знач НомерПеренаправления = 0)
+ Контекст = КонтекстВыполнения(Метод, НомерПеренаправления, Данные);
+
+ ПрименитьAWS4Аутентификацию(Метод, Данные, Конфигурация);
+ ПрименитьHawkАутентификацию(Метод, Данные, Конфигурация, Контекст);
+
Соединение = НовоеHTTPСоединениеСПереиспользованием(Конфигурация);
Запрос = Новый HTTPЗапрос(АдресРесурсаЗапроса(Конфигурация), Конфигурация.Заголовки);
- Если Метод = КлиентHTTPПовтИсп.МетодPOST() ИЛИ Метод = КлиентHTTPПовтИсп.МетодPUT() ИЛИ Метод = КлиентHTTPПовтИсп.МетодDELETE() Тогда
- Если ТипЗнч(Данные) = Тип("Строка") Тогда
- Запрос.УстановитьТелоИзСтроки(Данные, КодировкаИзДопПараметров(Конфигурация.ДополнительныеПараметры));
- Иначе
- Запрос.УстановитьТелоИзДвоичныхДанных(Данные);
- КонецЕсли;
+ Если МетодПодразумеваетТелоЗапроса(Метод) Тогда
+ Запрос.УстановитьТелоИзДвоичныхДанных(Данные);
КонецЕсли;
Возврат ОбработанныйОтвет(
Соединение.ВызватьHTTPМетод(Метод, Запрос, ИмяВыходногоФайлаИзДопПараметров(Конфигурация.ДополнительныеПараметры)),
Конфигурация,
- КонтекстВыполнения(Метод, НомерПеренаправления, Данные)
+ Контекст
);
КонецФункции
Функция КонтекстВыполнения(Знач Метод, Знач НомерПеренаправления, Знач Данные)
- Возврат Новый ФиксированнаяСтруктура("Метод, НомерПеренаправления, Данные", Метод, НомерПеренаправления, Данные);
+ Возврат Новый ФиксированнаяСтруктура("Метод, НомерПеренаправления, Данные, Значения", Метод, НомерПеренаправления, Данные, Новый Структура);
КонецФункции
Функция КонфигурацияЗапроса(Знач ИдентификаторРесурса, Знач ПараметрыЗапроса = Неопределено, ДополнительныеПараметры = Неопределено)
@@ -1269,10 +1471,49 @@
КонецЕсли;
ДанныеURI = СтруктураИдентификатораРесурса(ИдентификаторРесурса);
- Параметры = ОбъединениеПараметровЗапросаВСтроку(ДанныеURI.Параметры, ПараметрыЗапроса);
+ Параметры = ОбъединениеПараметровЗапроса(ДанныеURI.Параметры, ПараметрыЗапроса);
+ ПараметрыСтрокой = ПараметрыЗапросаСтрокой(Параметры);
Заголовки = ЗаголовкиЗапроса(ДанныеURI, ДополнительныеПараметры);
- Возврат Новый Структура("ДанныеURI, Параметры, Заголовки, ДополнительныеПараметры", ДанныеURI, Параметры, Заголовки, ДополнительныеПараметры);
+ Возврат Новый Структура("ДанныеURI, Параметры, ПараметрыСтрокой, Заголовки, ДополнительныеПараметры", ДанныеURI, Параметры, ПараметрыСтрокой, Заголовки, ДополнительныеПараметры);
+КонецФункции
+
+Функция МетодПодразумеваетТелоЗапроса(Знач Метод)
+ Возврат Метод = КлиентHTTPПовтИсп.МетодPOST()
+ ИЛИ Метод = КлиентHTTPПовтИсп.МетодPUT()
+ ИЛИ Метод = КлиентHTTPПовтИсп.МетодDELETE()
+ ИЛИ Метод = КлиентHTTPПовтИсп.МетодPATCH();
+КонецФункции
+
+Функция СоставляющиеАдресаРесурса(Знач АдресРесурса)
+ фРезультат = Новый Структура("Путь, Параметры, Фрагмент", "/", НовыеПараметрыЗапроса(), "");
+
+ АдресРесурса = СокрЛП(АдресРесурса);
+ Если АдресРесурса = "" ИЛИ АдресРесурса = "/" Тогда
+ Возврат фРезультат;
+ КонецЕсли;
+ Если НЕ СтрНачинаетсяС(АдресРесурса, "/") Тогда
+ АдресРесурса = "/" + АдресРесурса;
+ КонецЕсли;
+
+ ДлинаАдресаРесурса = СтрДлина(АдресРесурса);
+ ПозицияОкончанияПути = ДлинаАдресаРесурса;
+ ПозицияСимволаПараметров = СтрНайти(АдресРесурса, "?");
+ ПозицияСимволаФрагмента = СтрНайти(АдресРесурса, "#", , ?(ПозицияСимволаПараметров = 0, 1, ПозицияСимволаПараметров));
+ ПозицияОкончанияПути = ?(ПозицияСимволаПараметров = 0, ПозицияСимволаФрагмента, ПозицияСимволаПараметров);
+
+ фРезультат.Путь = Лев(
+ АдресРесурса,
+ ?(
+ ПозицияОкончанияПути = 0,
+ ДлинаАдресаРесурса,
+ ПозицияОкончанияПути - 1
+ )
+ );
+ фРезультат.Параметры = ПараметрыИдентификатора(АдресРесурса, ПозицияСимволаПараметров, ПозицияСимволаФрагмента);
+ фРезультат.Фрагмент = ?(ПозицияСимволаФрагмента = 0, "", Сред(АдресРесурса, ПозицияСимволаФрагмента + 1));
+
+ Возврат фРезультат;
КонецФункции
Функция ДлинаСхемыИдентификатораРесурса(ДанныеURI, Знач ИдентификаторРесурса)
@@ -1292,12 +1533,16 @@
Возврат фРезультат;
КонецФункции
-Процедура РазобратьОснованиеИдентификатораРесурса(ДанныеURI, Знач ИдентификаторРесурса, Знач ПозицияНачала, ПозицияОкончания)
+Процедура РазобратьОснованиеИдентификатораРесурса(ДанныеURI, Знач ИдентификаторРесурса, Знач ПозицияНачала, ПозицияПараметров, ПозицияФрагмента)
ОписаниеТипаЧисло = Новый ОписаниеТипов("Число");
ДлинаИдентификатораРесурса = СтрДлина(ИдентификаторРесурса);
ПозицияНачалаАдресаРесурса = СтрНайти(ИдентификаторРесурса, "/", , ПозицияНачала);
- ПозицияОкончания = СтрНайти(ИдентификаторРесурса, "?", , ПозицияНачала);
+ ПозицияПоиска = ?(ПозицияНачалаАдресаРесурса = 0, ПозицияНачала, ПозицияНачалаАдресаРесурса);
+ ПозицияПараметров = СтрНайти(ИдентификаторРесурса, "?", , ПозицияПоиска);
+ ПозицияПоиска = ?(ПозицияПараметров = 0, ПозицияПоиска, ПозицияПараметров);
+ ПозицияФрагмента = СтрНайти(ИдентификаторРесурса, "#", , ПозицияПоиска);
+ ПозицияОкончания = ?(ПозицияПараметров = 0, ПозицияФрагмента, ПозицияПараметров);
Обращение = Сред(
ИдентификаторРесурса,
@@ -1318,15 +1563,15 @@
Если ПозицияРазделителяАвторизации = 0 Тогда
ПозицияРазделителяАвторизации = ДлинаАвторизации + 1;
КонецЕсли;
+ ЗакодированныйПользователь = СокрЛП(Лев(Авторизация, ПозицияРазделителяАвторизации - 1));
+ ЗакодированныйПароль = Прав(Авторизация, ДлинаАвторизации - ПозицияРазделителяАвторизации);
+ МножествоСтрок = Новый Соответствие;
+ МножествоСтрок.Вставить(ЗакодированныйПользователь);
+ МножествоСтрок.Вставить(ЗакодированныйПароль);
- ЗакодированныеДанные = Новый Структура("Пользователь, Пароль");
- ЗакодированныеДанные.Пользователь = СокрЛП(Лев(Авторизация, ПозицияРазделителяАвторизации - 1));
- ЗакодированныеДанные.Пароль = Прав(Авторизация, ДлинаАвторизации - ПозицияРазделителяАвторизации);
-
- РаскодированныеДанные = КлиентHTTPВызовСервера.РаскодированныеСтроки(ЗакодированныеДанные);
-
- ДанныеURI.Пользователь = РаскодированныеДанные.Пользователь;
- ДанныеURI.Пароль = РаскодированныеДанные.Пароль;
+ МножествоСтрок = КлиентHTTPВызовСервера.РаскодированныеСтрокиURLвURL(МножествоСтрок);
+ ДанныеURI.Пользователь = МножествоСтрок.Получить(ЗакодированныйПользователь);
+ ДанныеURI.Пароль = МножествоСтрок.Получить(ЗакодированныйПароль);
КонецЕсли;
ИмяХоста = Прав(Обращение, ДлинаОбращения - ПозицияПослеАвторизации);
@@ -1347,7 +1592,7 @@
ДанныеURI.Сервер = ?(ПозицияПорта = 0, ИмяХоста, Лев(ИмяХоста, ПозицияПорта - 1));
Если ПозицияНачалаАдресаРесурса > 0 Тогда
- ДанныеURI.АдресРесурса = Сред(
+ ДанныеURI.Путь = Сред(
ИдентификаторРесурса,
ПозицияНачалаАдресаРесурса,
?(
@@ -1359,17 +1604,27 @@
КонецЕсли;
КонецПроцедуры
-Функция ПараметрыИдентификатора(Знач ИдентификаторРесурса, Знач ПозицияНачала) Экспорт
+Функция ПараметрыИдентификатора(Знач ИдентификаторРесурса, Знач ПозицияНачала, Знач ПозицияОкончания)
фРезультат = НовыеПараметрыЗапроса();
+ ДлинаИдентификатораРесурса = СтрДлина(ИдентификаторРесурса);
ПараметрыСтрока = ?(
- ПозицияНачала = 0,
+ ПозицияНачала = 0 ИЛИ ПозицияНачала = ДлинаИдентификатораРесурса,
"",
- Сред(ИдентификаторРесурса, ПозицияНачала + 1)
+ Сред(
+ ИдентификаторРесурса,
+ ПозицияНачала + 1,
+ ?(
+ ПозицияОкончания = 0,
+ ДлинаИдентификатораРесурса,
+ ПозицияОкончания - 1
+ ) - ПозицияНачала
+ )
);
- Параметры = СтрРазделить(ПараметрыСтрока, "&", Ложь);
- Для Каждого Параметр Из Параметры Цикл
+ Параметры = Новый Массив;
+ МножествоСтрок = Новый Соответствие;
+ Для Каждого Параметр Из СтрРазделить(ПараметрыСтрока, "&", Ложь) Цикл
ПозицияРазделителя = СтрНайти(Параметр, "=");
Если ПозицияРазделителя = 0 Тогда
ПозицияРазделителя = СтрДлина(Параметр) + 1;
@@ -1382,6 +1637,17 @@
ЗначениеПараметра = Сред(Параметр, ПозицияРазделителя + 1);
+ Параметры.Добавить(Новый Структура("Ключ, Значение", ИмяПараметра, ЗначениеПараметра));
+ МножествоСтрок.Вставить(ИмяПараметра);
+ МножествоСтрок.Вставить(ЗначениеПараметра);
+ КонецЦикла;
+
+ МножествоСтрок = КлиентHTTPВызовСервера.РаскодированныеСтрокиURLвURL(МножествоСтрок);
+
+ Для Каждого Параметр Из Параметры Цикл
+ ИмяПараметра = МножествоСтрок.Получить(Параметр.Ключ);
+ ЗначениеПараметра = МножествоСтрок.Получить(Параметр.Значение);
+
ДобавитьПараметр(фРезультат, ИмяПараметра, ЗначениеПараметра);
КонецЦикла;
@@ -1390,34 +1656,39 @@
Функция СтруктураИдентификатораРесурса(Знач ИдентификаторРесурса)
фРезультат = Новый Структура(
- "Сервер, АдресРесурса, Пользователь, Пароль, Порт, ЗащищенноеСоединение, Параметры",
+ "Сервер, Путь, Пользователь, Пароль, Порт, ЗащищенноеСоединение, Параметры, Фрагмент",
"", // Сервер
- "/", // АдресРесурса
+ "/", // Путь
"", // Пользователь
"", // Пароль
80, // Порт
Ложь, // ЗащищенноеСоединение
- Неопределено // Параметры
+ Неопределено, // Параметры
+ "" // Фрагмент
);
Если ТипЗнч(ИдентификаторРесурса) = Тип("Структура") Тогда
+ АдресРесурса = СоставляющиеАдресаРесурса(ИдентификаторРесурса.АдресРесурса);
фРезультат.Сервер = ИдентификаторРесурса.Сервер;
- фРезультат.АдресРесурса = ИдентификаторРесурса.АдресРесурса;
+ фРезультат.Путь = АдресРесурса.Путь;
фРезультат.Порт = ИдентификаторРесурса.Порт;
- фРезультат.Параметры = НовыеПараметрыЗапроса();
+ фРезультат.Параметры = АдресРесурса.Параметры;
фРезультат.ЗащищенноеСоединение = ИдентификаторРесурса.ЗащищенноеСоединение;
фРезультат.Пользователь = ИдентификаторРесурса.Пользователь;
фРезультат.Пароль = ИдентификаторРесурса.Пароль;
+ фРезультат.Фрагмент = АдресРесурса.Фрагмент;
Возврат фРезультат;
КонецЕсли;
ПозицияНачалаПоиска = ДлинаСхемыИдентификатораРесурса(фРезультат, ИдентификаторРесурса);
- ПозицияНачалаСтрокиПараметров = 0;
- РазобратьОснованиеИдентификатораРесурса(фРезультат, ИдентификаторРесурса, ПозицияНачалаПоиска, ПозицияНачалаСтрокиПараметров);
+ ПозицияСимволаПараметров = 0;
+ ПозицияСимволаФрагмента = 0;
+ РазобратьОснованиеИдентификатораРесурса(фРезультат, ИдентификаторРесурса, ПозицияНачалаПоиска, ПозицияСимволаПараметров, ПозицияСимволаФрагмента);
- фРезультат.Параметры = ПараметрыИдентификатора(ИдентификаторРесурса, ПозицияНачалаСтрокиПараметров);
+ фРезультат.Параметры = ПараметрыИдентификатора(ИдентификаторРесурса, ПозицияСимволаПараметров, ПозицияСимволаФрагмента);
+ фРезультат.Фрагмент = ?(ПозицияСимволаФрагмента = 0, "", Сред(ИдентификаторРесурса, ПозицияСимволаФрагмента + 1));
Возврат фРезультат;
КонецФункции
@@ -1474,18 +1745,18 @@
);
КонецФункции
-Функция ОбъединениеПараметровЗапросаВСтроку(Знач ПараметрыURI, Знач ПараметрыЗапроса)
- МножествоПараметров = Новый Соответствие;
+Функция ОбъединениеПараметровЗапроса(Знач ПараметрыURI, Знач ПараметрыЗапроса)
+ фРезультат = Новый Соответствие;
Для Каждого КЗ Из ПараметрыURI Цикл
- МножествоПараметров.Вставить(КЗ.Ключ, КЗ.Значение);
+ фРезультат.Вставить(КЗ.Ключ, КЗ.Значение);
КонецЦикла;
Для Каждого КЗ Из ПараметрыЗапроса Цикл
- МножествоПараметров.Вставить(КЗ.Ключ, КЗ.Значение);
+ фРезультат.Вставить(КЗ.Ключ, КЗ.Значение);
КонецЦикла;
- Возврат ПараметрыЗапросаСтрокой(МножествоПараметров);
+ Возврат фРезультат;
КонецФункции
Функция ЗаголовкиЗапроса(Знач ДанныеURI, ДополнительныеПараметры)
@@ -1501,6 +1772,8 @@
КонецЦикла;
КонецЕсли;
+ ДобавитьХостВЗаголовкиЗапроса(фРезультат, ДанныеURI);
+ ДобавитьАгентаПользователяВЗаголовкиЗапроса(фРезультат, ДополнительныеПараметры);
ДобавитьТипКонтентаВЗаголовкиЗапроса(фРезультат, ДополнительныеПараметры);
ДобавитьКодировкуВЗаголовкиЗапроса(фРезультат, ДополнительныеПараметры);
ДобавитьРазделительПолейФормыВЗаголовкиЗапроса(фРезультат, ДополнительныеПараметры);
@@ -1520,23 +1793,47 @@
Возврат ?(ДополнительныеПараметры.Свойство("ИмяВыходногоФайла"), ДополнительныеПараметры.ИмяВыходногоФайла, "");
КонецФункции
+Процедура ДобавитьХостВЗаголовкиЗапроса(Заголовки, Знач ДанныеURI)
+ Хост = КлиентHTTPСлужебный.НормализованныйАдресСервера(ДанныеURI.Сервер);
+
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокХост(), ?(
+ ЗначениеЗаполнено(ДанныеURI.Порт)
+ И (ДанныеURI.ЗащищенноеСоединение И ДанныеURI.Порт <> 443
+ ИЛИ НЕ ДанныеURI.ЗащищенноеСоединение И ДанныеURI.Порт <> 80),
+ СтрШаблон("%1:%2", Хост, Формат(ДанныеURI.Порт, "ЧГ=")),
+ Хост
+ ));
+КонецПроцедуры
+
+Процедура ДобавитьАгентаПользователяВЗаголовкиЗапроса(Заголовки, Знач ДополнительныеПараметры)
+ Перем АгентПользователя;
+
+ ДополнительныеПараметры.Свойство("АгентПользователя", АгентПользователя);
+ Если ЗначениеЗаполнено(АгентПользователя) Тогда
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокАгентПользователя(), АгентПользователя);
+ КонецЕсли;
+КонецПроцедуры
+
Процедура ДобавитьТипКонтентаВЗаголовкиЗапроса(Заголовки, Знач ДополнительныеПараметры)
Если ДополнительныеПараметры.Свойство("ТипMIME") Тогда
- Заголовки.Вставить("Content-Type", ДополнительныеПараметры.ТипMIME);
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокТипКонтента(), ДополнительныеПараметры.ТипMIME);
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьКодировкуВЗаголовкиЗапроса(Заголовки, Знач ДополнительныеПараметры)
- ТекущееЗначение = Заголовки.Получить("Content-Type");
+ ТекущееЗначение = Заголовки.Получить(КлиентHTTPПовтИсп.ЗаголовокТипКонтента());
Если ДополнительныеПараметры.Свойство("Кодировка") И ТекущееЗначение <> Неопределено Тогда
- Заголовки.Вставить("Content-Type", ТекущееЗначение + "; charset=" + КодировкаИзДопПараметров(ДополнительныеПараметры));
+ Заголовки.Вставить(
+ КлиентHTTPПовтИсп.ЗаголовокТипКонтента(),
+ ТекущееЗначение + "; charset=" + КодировкаИзДопПараметров(ДополнительныеПараметры)
+ );
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьСжатиеВЗаголовкиЗапроса(Заголовки, Знач ДополнительныеПараметры)
Если ДополнительныеПараметры.Свойство("СжатиеОтвета") Тогда
- Заголовки.Вставить("Accept-Encoding", ДополнительныеПараметры.СжатиеОтвета);
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокДопустимыеСпособыКодированияОтвета(), ДополнительныеПараметры.СжатиеОтвета);
КонецЕсли;
КонецПроцедуры
@@ -1545,11 +1842,9 @@
Возврат;
КонецЕсли;
- Если ДополнительныеПараметры.Сессия.Свойство("Печенье") Тогда
- Печенье = ПеченьеДляURI(ДанныеURI, ДополнительныеПараметры.Сессия.Печенье);
- Если ЗначениеЗаполнено(Печенье) Тогда
- Заголовки.Вставить("Cookie", СтрСоединить(Печенье, "; "));
- КонецЕсли;
+ Значение = ЗначениеЗаголовкаCookie(ДанныеURI, ДополнительныеПараметры.Сессия);
+ Если ЗначениеЗаполнено(Значение) Тогда
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокПеченье(), Значение);
КонецЕсли;
КонецПроцедуры
@@ -1568,6 +1863,10 @@
ДополнительныеПараметры.Вставить("АвторизоватьсяDigest");
ИначеЕсли ТипАутентификации = "Bearer" Тогда
ДобавитьBearerАутентификациюВЗаголовкиЗапроса(Заголовки, ДополнительныеПараметры.Аутентификация);
+ ИначеЕсли ТипАутентификации = "AWS4" Тогда
+ ЗарегистрироватьAWS4Аутентификацию(ДополнительныеПараметры);
+ ИначеЕсли ТипАутентификации = "Hawk" Тогда
+ ЗарегистрироватьHawkАутентификацию(ДополнительныеПараметры);
Иначе
ВызватьИсключение СтрШаблон("Неизвестный тип аутентификации: %1", ТипАутентификации);
КонецЕсли;
@@ -1576,7 +1875,7 @@
Процедура ДобавитьBasicАутентификациюВЗаголовкиЗапроса(Заголовки, Знач ДанныеАутентификации)
СтрокаАутентификации = КлиентHTTPСлужебный.СтрокаBasicАвторизации(ДанныеАутентификации.Пользователь, ДанныеАутентификации.Пароль);
- Заголовки.Вставить("Authorization", "Basic " + СтрокаАутентификации);
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокТипАутентификации(), "Basic " + СтрокаАутентификации);
КонецПроцедуры
Процедура УстановитьNTLMАутентификацию(ДополнительныеПараметры, Знач ДанныеАутентификации)
@@ -1586,23 +1885,82 @@
КонецПроцедуры
Процедура ДобавитьBearerАутентификациюВЗаголовкиЗапроса(Заголовки, Знач ДанныеАутентификации)
- Заголовки.Вставить("Authorization", "Bearer " + ДанныеАутентификации.Пользователь);
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокТипАутентификации(), "Bearer " + ДанныеАутентификации.Токен);
+КонецПроцедуры
+
+Процедура ЗарегистрироватьAWS4Аутентификацию(ДополнительныеПараметры)
+ ДополнительныеПараметры.Вставить("АвторизоватьсяAWS4", ДополнительныеПараметры.Аутентификация);
+КонецПроцедуры
+
+Процедура ЗарегистрироватьHawkАутентификацию(ДополнительныеПараметры)
+ ДополнительныеПараметры.Вставить("АвторизоватьсяHawk", ДополнительныеПараметры.Аутентификация);
КонецПроцедуры
+Процедура ПрименитьAWS4Аутентификацию(Знач Метод, Знач Данные, Конфигурация)
+ Если НЕ Конфигурация.ДополнительныеПараметры.Свойство("АвторизоватьсяAWS4") Тогда
+ Возврат;
+ КонецЕсли;
+
+ ДанныеАдресВХ = ПоместитьВоВременноеХранилище(?(Данные = Неопределено, "", Данные), Новый УникальныйИдентификатор);
+ Для Каждого Заголовок Из КлиентHTTPВызовСервера.ЗаголовкиAWS4(Метод, Конфигурация, ДанныеАдресВХ) Цикл
+ Конфигурация.Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение);
+ КонецЦикла;
+КонецПроцедуры
+
+Процедура ПрименитьHawkАутентификацию(Знач Метод, Знач Данные, Конфигурация, Контекст)
+ Если НЕ Конфигурация.ДополнительныеПараметры.Свойство("АвторизоватьсяHawk") Тогда
+ Возврат;
+ КонецЕсли;
+
+ ДанныеАдресВХ = ?(
+ Данные = Неопределено,
+ Неопределено,
+ ПоместитьВоВременноеХранилище(Данные, Новый УникальныйИдентификатор)
+ );
+
+ ЗначениеЗаголовкаHawk = КлиентHTTPВызовСервера.ЗаголовокHawk(Метод, Конфигурация, ДанныеАдресВХ);
+ Конфигурация.Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокТипАутентификации(), ЗначениеЗаголовкаHawk);
+
+ Контекст.Значения.Вставить("АутентификацияHawk", КонтекстАутентификацииHawk(Контекст, Конфигурация));
+КонецПроцедуры
+
+Функция КонтекстАутентификацииHawk(Контекст, Конфигурация)
+ Аутентификация = Конфигурация.ДополнительныеПараметры.АвторизоватьсяHawk;
+ Возврат Новый ФиксированнаяСтруктура(
+ "Ключ, Дополнение, ИдентификаторПриложения, Делегирование, Метод, Хост, Порт, Путь, ВременнаяМетка, РазовоеСлово",
+ Аутентификация.Ключ,
+ Аутентификация.Дополнение,
+ Аутентификация.ИдентификаторПриложения,
+ Аутентификация.Делегирование,
+ Контекст.Метод,
+ Конфигурация.ДанныеURI.Сервер,
+ Конфигурация.ДанныеURI.Порт,
+ Конфигурация.ДанныеURI.Путь,
+ Аутентификация.ВременнаяМетка,
+ Аутентификация.РазовоеСлово
+ );
+КонецФункции
+
Процедура ДобавитьРазделительПолейФормыВЗаголовкиЗапроса(Заголовки, Знач ДополнительныеПараметры)
- ТекущееЗначение = Заголовки.Получить("Content-Type");
+ ТекущееЗначение = Заголовки.Получить(КлиентHTTPПовтИсп.ЗаголовокТипКонтента());
Если ДополнительныеПараметры.Свойство("Разделитель") И ТекущееЗначение <> Неопределено Тогда
- Заголовки.Вставить("Content-Type", ТекущееЗначение + "; boundary=" + ДополнительныеПараметры.Разделитель);
+ Заголовки.Вставить(
+ КлиентHTTPПовтИсп.ЗаголовокТипКонтента(),
+ ТекущееЗначение + "; boundary=" + ДополнительныеПараметры.Разделитель
+ );
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьРазмерДанныхВЗаголовкиЗапроса(Заголовки, Знач ДополнительныеПараметры, Знач Данные)
Если ТипЗнч(Данные) = Тип("ДвоичныеДанные") Тогда
- Заголовки.Вставить("Content-Length", XMLСтрока(Данные.Размер()));
+ Заголовки.Вставить(КлиентHTTPПовтИсп.ЗаголовокРазмерКонтента(), XMLСтрока(Данные.Размер()));
ИначеЕсли ТипЗнч(Данные) = Тип("Строка") Тогда
Кодировка = КодировкаИзДопПараметров(ДополнительныеПараметры);
- Заголовки.Вставить("Content-Length", XMLСтрока(КлиентHTTPСлужебный.РазмерТекстовыхДанных(Данные, Кодировка)));
+ Заголовки.Вставить(
+ КлиентHTTPПовтИсп.ЗаголовокРазмерКонтента(),
+ XMLСтрока(КлиентHTTPСлужебный.РазмерТекстовыхДанных(Данные, Кодировка))
+ );
Иначе
ВызватьИсключение "Неизвестный тип данных: " + ТипЗнч(Данные);
КонецЕсли;
@@ -1647,12 +2005,37 @@
ЗаписьДанныхФормы.ЗаписатьСтроку("");
КонецПроцедуры
+Функция ПеренаправлениеЗапросаHTTP(Знач НовыйИдентификаторРесурса, Знач Ответ, Знач Конфигурация, Знач КонтекстВыполнения)
+ Метод = КонтекстВыполнения.Метод;
+ Данные = КонтекстВыполнения.Данные;
+ Если (
+ Ответ.КодСостояния = КлиентHTTPПовтИсп.КодСостоянияПеремещен()
+ ИЛИ Ответ.КодСостояния = КлиентHTTPПовтИсп.КодСостоянияНайден()
+ ) И Конфигурация.ДополнительныеПараметры.Сессия.Свойство("ПеренаправлениеКакGET")
+ Тогда
+ Метод = КлиентHTTPПовтИсп.МетодGET();
+ Данные = Неопределено;
+
+ Конфигурация.Заголовки.Удалить(КлиентHTTPПовтИсп.ЗаголовокРазмерКонтента());
+ КонецЕсли;
+
+ Конфигурация.ДанныеURI = СтруктураИдентификатораРесурса(НовыйИдентификаторРесурса);
+ Конфигурация.Параметры = ОбъединениеПараметровЗапроса(Конфигурация.ДанныеURI.Параметры, НовыеПараметрыЗапроса());
+ Конфигурация.ПараметрыСтрокой = ПараметрыЗапросаСтрокой(Конфигурация.Параметры);
+
+ Возврат ВыполненныйЗапросHTTP(Метод, Конфигурация, Данные, КонтекстВыполнения.НомерПеренаправления + 1);
+КонецФункции
+
+Функция НовыйОбъектОбработанногоОтвета()
+ Возврат Новый Структура("КодСостояния, Заголовки, Тело, ИмяФайлаТела, КонтекстВыполнения");
+КонецФункции
+
Функция ОбработанныйОтвет(Знач Ответ, Знач Конфигурация, Знач КонтекстВыполнения)
Если НЕ Конфигурация.ДополнительныеПараметры.Свойство("Сессия") Тогда
- Возврат ОбъектОбработанногоОтвета(Ответ, Конфигурация.ДополнительныеПараметры);
+ Возврат ОбъектОбработанногоОтвета(Ответ, Конфигурация.ДополнительныеПараметры, КонтекстВыполнения);
КонецЕсли;
- Печенье = ЗначениеЗаголовка("Set-Cookie", Ответ.Заголовки);
+ Печенье = ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокОтветаСПеченьем(), Ответ.Заголовки);
Если Печенье <> Неопределено Тогда
Попытка
КлиентHTTPВызовСервера.ПринятьПеченье(Конфигурация.ДополнительныеПараметры.Сессия, Печенье, Конфигурация.ДанныеURI.Сервер);
@@ -1668,54 +2051,59 @@
Сессия = Конфигурация.ДополнительныеПараметры.Сессия;
НовыйИдентификаторРесурса = ИдентификаторПеренаправления(Ответ.КодСостояния, Ответ.Заголовки);
Если ЗначениеЗаполнено(НовыйИдентификаторРесурса) И КонтекстВыполнения.НомерПеренаправления <= Сессия.ПорогПеренаправлений Тогда
- Конфигурация.ДанныеURI = СтруктураИдентификатораРесурса(НовыйИдентификаторРесурса);
- Конфигурация.Параметры = ОбъединениеПараметровЗапросаВСтроку(Конфигурация.ДанныеURI.Параметры, НовыеПараметрыЗапроса());
-
- Возврат ВыполнитьЗапросHTTP(КонтекстВыполнения.Метод, Конфигурация, КонтекстВыполнения.Данные, КонтекстВыполнения.НомерПеренаправления + 1);
+ Возврат ПеренаправлениеЗапросаHTTP(НовыйИдентификаторРесурса, Ответ, Конфигурация, КонтекстВыполнения);
КонецЕсли;
Если Ответ.КодСостояния = КлиентHTTPПовтИсп.КодСостоянияНеАвторизовано() И Конфигурация.ДополнительныеПараметры.Свойство("АвторизоватьсяDigest") Тогда
- РецептАвторизации = ЗначениеЗаголовка("WWW-Authenticate", Ответ.Заголовки);
+ РецептАвторизации = ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокОтветаМетодыАутентификации(), Ответ.Заголовки);
Если СтрНачинаетсяС(НРег(РецептАвторизации), "digest") Тогда
КонтекстВыполненияАдресВХ = ПоместитьВоВременноеХранилище(КонтекстВыполнения, Новый УникальныйИдентификатор);
Конфигурация.ДополнительныеПараметры.Удалить("АвторизоватьсяDigest");
Сессия.Вставить("ПараметрыDigest", ПараметрыDigest(РецептАвторизации));
- Конфигурация.Заголовки.Вставить("Authorization", КлиентHTTPВызовСервера.ЗаголовокDigest(Конфигурация, КонтекстВыполненияАдресВХ));
+ Конфигурация.Заголовки.Вставить(
+ КлиентHTTPПовтИсп.ЗаголовокТипАутентификации(),
+ КлиентHTTPВызовСервера.ЗаголовокDigest(Конфигурация, КонтекстВыполненияАдресВХ)
+ );
- Возврат ВыполнитьЗапросHTTP(КонтекстВыполнения.Метод, Конфигурация, КонтекстВыполнения.Данные, КонтекстВыполнения.НомерПеренаправления + 1);
+ Возврат ВыполненныйЗапросHTTP(КонтекстВыполнения.Метод, Конфигурация, КонтекстВыполнения.Данные, КонтекстВыполнения.НомерПеренаправления + 1);
КонецЕсли;
КонецЕсли;
- Возврат ОбъектОбработанногоОтвета(Ответ, Конфигурация.ДополнительныеПараметры);
+ Возврат ОбъектОбработанногоОтвета(Ответ, Конфигурация.ДополнительныеПараметры, КонтекстВыполнения);
КонецФункции
-Функция ОбъектОбработанногоОтвета(Знач Ответ, Знач ДополнительныеПараметры)
- Возврат Новый ФиксированнаяСтруктура(
- "КодСостояния, Заголовки, Тело, ИмяФайлаТела",
- Ответ.КодСостояния,
- Ответ.Заголовки,
- ТелоОтвета(Ответ, ДополнительныеПараметры),
- Ответ.ПолучитьИмяФайлаТела()
- );
+Функция ОбъектОбработанногоОтвета(Знач Ответ, Знач ДополнительныеПараметры, Знач КонтекстВыполнения)
+ фРезультат = НовыйОбъектОбработанногоОтвета();
+ фРезультат.КодСостояния = Ответ.КодСостояния;
+ фРезультат.Заголовки = Ответ.Заголовки;
+ фРезультат.Тело = ТелоОтвета(Ответ, ДополнительныеПараметры);
+ фРезультат.ИмяФайлаТела = Ответ.ПолучитьИмяФайлаТела();
+ фРезультат.КонтекстВыполнения = КонтекстВыполнения.Значения;
+
+ Возврат Новый ФиксированнаяСтруктура(фРезультат);
КонецФункции
Функция ТелоОтвета(Знач Ответ, Знач ДополнительныеПараметры)
ДанныеТелаОтвета = ?(
- ЗначениеЗаголовка("Content-Encoding", Ответ.Заголовки) = Неопределено,
+ ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокОтветаСжатиеТела(), Ответ.Заголовки) = Неопределено,
Ответ.ПолучитьТелоКакДвоичныеДанные(),
Декомпрессия(Ответ.ПолучитьТелоКакПоток())
);
- фРезультат = ДанныеТелаОтвета;
-
- Если НЕ ДополнительныеПараметры.Свойство("ПрочитатьТелоОтветаКак") Тогда
- Возврат фРезультат;
- КонецЕсли;
+ Возврат ?(
+ ДополнительныеПараметры.Свойство("ПрочитатьТелоОтветаКак"),
+ ПреобразованноеТелоОтвета(Ответ, ДанныеТелаОтвета, ДополнительныеПараметры.ПрочитатьТелоОтветаКак),
+ ДанныеТелаОтвета
+ );
+КонецФункции
+
+Функция ПреобразованноеТелоОтвета(Знач Ответ, Знач ДанныеТелаОтвета, Знач СпособЧтения) Экспорт
+ Перем фРезультат;
Кодировка = КлиентHTTPПовтИсп.КодировкаПоУмолчанию();
- ТипСодержимого = ЗначениеЗаголовка("Content-Type", Ответ.Заголовки);
+ ТипСодержимого = КлиентHTTPКлиентСервер.ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокТипКонтента(), Ответ.Заголовки);
Если ТипСодержимого <> Неопределено Тогда
ПозицияРазделителя = СтрНайти(ТипСодержимого, ";");
Если ПозицияРазделителя > 0 Тогда
@@ -1723,7 +2111,6 @@
КонецЕсли;
КонецЕсли;
- СпособЧтения = ДополнительныеПараметры.ПрочитатьТелоОтветаКак;
Если СпособЧтения.Формат = ФорматТелаОтветаТекст() Тогда
фРезультат = ПолучитьСтрокуИзДвоичныхДанных(ДанныеТелаОтвета, Кодировка);
ИначеЕсли СпособЧтения.Формат = ФорматТелаОтветаJSON() Тогда
@@ -1783,7 +2170,7 @@
Получатель = КлиентHTTPСлужебный.НормализованныйАдресСервера(ДанныеURI.Сервер);
ДатаЗапроса = КлиентHTTPВызовСервера.ТекущаяУниверсальнаяДатаНаСервере();
- ВзятьПеченье(фРезультат, Печенье, Получатель, ДатаЗапроса, ДанныеURI.АдресРесурса, ДанныеURI.ЗащищенноеСоединение);
+ ВзятьПеченье(фРезультат, Печенье, Получатель, ДатаЗапроса, ДанныеURI.Путь, ДанныеURI.ЗащищенноеСоединение);
Если фРезультат.Количество() > 0 Тогда
Возврат Новый ФиксированныйМассив(фРезультат);
КонецЕсли;
@@ -1792,7 +2179,7 @@
Пока Части.Количество() > 1 Цикл
Получатель = "." + СтрСоединить(Части, ".");
- ВзятьПеченье(фРезультат, Печенье, Получатель, ДатаЗапроса, ДанныеURI.АдресРесурса, ДанныеURI.ЗащищенноеСоединение);
+ ВзятьПеченье(фРезультат, Печенье, Получатель, ДатаЗапроса, ДанныеURI.Путь, ДанныеURI.ЗащищенноеСоединение);
Если фРезультат.Количество() > 0 Тогда
Прервать;
КонецЕсли;
@@ -1803,9 +2190,9 @@
Возврат Новый ФиксированныйМассив(фРезультат);
КонецФункции
-Процедура ВзятьПеченье(ПеченьеПолучателя, Печенье, Знач Получатель, Знач ДатаЗапроса, Знач АдресРесурса, Знач ЗащищенноеСоединение)
+Процедура ВзятьПеченье(ПеченьеПолучателя, Печенье, Знач Получатель, Знач ДатаЗапроса, Знач Путь, Знач ЗащищенноеСоединение)
ИмяСрок = КлиентHTTPПовтИсп.СвойствоПеченькаСрок();
- ИмяАдресРесурса = КлиентHTTPПовтИсп.СвойствоПеченькаАдресРесурса();
+ ИмяПуть = КлиентHTTPПовтИсп.СвойствоПеченькаАдресРесурса();
ИмяЗащищенноеСоединение = КлиентHTTPПовтИсп.СвойствоПеченькаЗащищенноеСоединение();
Печеньки = Печенье.Получить(Получатель);
@@ -1821,7 +2208,7 @@
ПеченькиНаУдаление.Добавить(КЗ.Ключ);
Продолжить;
КонецЕсли;
- Если Печенька.Свойство(ИмяАдресРесурса) И НЕ СтрНачинаетсяС(АдресРесурса, Печенька[ИмяАдресРесурса]) Тогда
+ Если Печенька.Свойство(ИмяПуть) И НЕ СтрНачинаетсяС(Путь, Печенька[ИмяПуть]) Тогда
Продолжить;
КонецЕсли;
Если Печенька.Свойство(ИмяЗащищенноеСоединение) И НЕ ЗащищенноеСоединение Тогда
@@ -1857,29 +2244,28 @@
КонецЦикла;
КонецПроцедуры
-Функция АдресРесурсаЗапроса(Знач Конфигурация)
- Возврат Конфигурация.ДанныеURI.АдресРесурса + Конфигурация.Параметры;
-КонецФункции
-
-Функция ЗначениеЗаголовка(Знач ИмяЗаголовка, Знач Заголовки)
- фРезультат = Неопределено;
- ИмяЗаголовка = НРег(ИмяЗаголовка);
+Функция ЗначениеЗаголовкаCookie(Знач ДанныеURI, Знач Сессия)
+ Если НЕ Сессия.Свойство("Печенье") Тогда
+ Возврат Неопределено;
+ КонецЕсли;
- Для Каждого КЗ Из Заголовки Цикл
- Если НРег(КЗ.Ключ) = ИмяЗаголовка Тогда
- фРезультат = КЗ.Значение;
- Прервать;
- КонецЕсли;
- КонецЦикла;
+ Печенье = ПеченьеДляURI(ДанныеURI, Сессия.Печенье);
- Возврат фРезультат;
+ Возврат ?(ЗначениеЗаполнено(Печенье), СтрСоединить(Печенье, "; "), "");
+КонецФункции
+
+Функция АдресРесурсаЗапроса(Знач Конфигурация)
+ Возврат Конфигурация.ДанныеURI.Путь +
+ Конфигурация.ПараметрыСтрокой +
+ ?(ПустаяСтрока(Конфигурация.ДанныеURI.Фрагмент), "", "#") +
+ Конфигурация.ДанныеURI.Фрагмент;
КонецФункции
Функция ИдентификаторПеренаправления(Знач КодСостояния, Знач Заголовки)
Возврат ?(
КлиентHTTPПовтИсп.КодыСостоянияПеренаправления().Получить(КодСостояния) = Неопределено,
Неопределено,
- КлиентHTTPВызовСервера.РаскодированныйИдентификаторРесурса(ЗначениеЗаголовка("Location", Заголовки))
+ КлиентHTTPВызовСервера.РаскодированныйИдентификаторРесурса(СокрЛП(ЗначениеЗаголовка(КлиентHTTPПовтИсп.ЗаголовокОтветаПеренаправление(), Заголовки)))
);
КонецФункции
@@ -1887,6 +2273,26 @@
Возврат Новый ФиксированнаяСтруктура("Тип, Пользователь, Пароль", Тип, Пользователь, Пароль);
КонецФункции
+Функция ОбъектАутентификацииBearer(Знач Токен)
+ Возврат Новый ФиксированнаяСтруктура("Тип, Токен", "Bearer", Токен);
+КонецФункции
+
+Функция ОбъектАутентификацииAWS4(Знач КлючДоступа, Знач СекретныйКлюч, Знач Регион, Знач Сервис)
+ Возврат Новый ФиксированнаяСтруктура("Тип, КлючДоступа, СекретныйКлюч, Регион, Сервис", "AWS4", КлючДоступа, СекретныйКлюч, Регион, Сервис);
+КонецФункции
+
+Функция ОбъектАутентификацииHawk(Знач Идентификатор, Знач Ключ, Знач Дополнение, Знач ИдентификаторПриложения, Знач Делегирование)
+ Возврат Новый ФиксированнаяСтруктура(
+ "Тип, Идентификатор, Ключ, Дополнение, ИдентификаторПриложения, Делегирование",
+ "Hawk",
+ Идентификатор,
+ Ключ,
+ Дополнение,
+ ИдентификаторПриложения,
+ Делегирование
+ );
+КонецФункции
+
Функция ПараметрыDigest(Знач РецептАвторизации)
фРезультат = Новый Структура("algorithm, realm, nonce, qop, opaque");
@@ -1962,14 +2368,6 @@
Возврат фРезультат;
КонецФункции
-Функция ФорматированноеИмяПараметраЗапроса(Знач Имя)
- Возврат СтрЗаменить(ФорматированноеЗначениеПараметраЗапроса(Имя), "=", "%3D");
-КонецФункции
-
-Функция ФорматированноеЗначениеПараметраЗапроса(Знач Значение)
- Возврат СтрЗаменить(СтрЗаменить(СтрЗаменить(Значение, Символы.ПС, ""), "#", "%23"), "&", "%26");
-КонецФункции
-
Функция СпособЧтенияТелаОтвета(Знач Формат, Знач Параметры = Неопределено)
Возврат Новый Структура("Формат, Параметры", Формат, Параметры);
КонецФункции
diff --git "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\237\320\276\320\262\321\202\320\230\321\201\320\277/Ext/Module.bsl" "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\237\320\276\320\262\321\202\320\230\321\201\320\277/Ext/Module.bsl"
index d731622..9621379 100644
--- "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\237\320\276\320\262\321\202\320\230\321\201\320\277/Ext/Module.bsl"
+++ "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\237\320\276\320\262\321\202\320\230\321\201\320\277/Ext/Module.bsl"
@@ -200,6 +200,15 @@
Возврат КлиентHTTPПовтИсп.КодыСостояния().Перенаправления.Найден;
КонецФункции
+// Возвращает код состояния HTTP-сервера 303
+//
+// Возвращаемое значение:
+// Число - код состояния
+//
+Функция КодСостоянияПросмотрДругихРесурсов() Экспорт
+ Возврат КлиентHTTPПовтИсп.КодыСостояния().Перенаправления.ПросмотрДругихРесурсов;
+КонецФункции
+
// Возвращает код состояния HTTP-сервера 307
//
// Возвращаемое значение:
@@ -209,6 +218,15 @@
Возврат КлиентHTTPПовтИсп.КодыСостояния().Перенаправления.ВременноеПеренаправление;
КонецФункции
+// Возвращает код состояния HTTP-сервера 308
+//
+// Возвращаемое значение:
+// Число - код состояния
+//
+Функция КодСостоянияПеренаправление() Экспорт
+ Возврат КлиентHTTPПовтИсп.КодыСостояния().Перенаправления.ПеренаправлениеНаПостояннойОснове;
+КонецФункции
+
// Возвращает код состояния HTTP-сервера 400
//
// Возвращаемое значение:
@@ -345,9 +363,9 @@
фРезультат = Новый Соответствие;
фРезультат.Вставить(КлиентHTTPПовтИсп.КодСостоянияПеремещен(), Истина);
фРезультат.Вставить(КлиентHTTPПовтИсп.КодСостоянияНайден(), Истина);
- фРезультат.Вставить(КлиентHTTPПовтИсп.КодыСостояния().Перенаправления.ПросмотрДругихРесурсов, Истина);
+ фРезультат.Вставить(КлиентHTTPПовтИсп.КодСостоянияПросмотрДругихРесурсов(), Истина);
фРезультат.Вставить(КлиентHTTPПовтИсп.КодСостоянияВременноеПеренаправление(), Истина);
- фРезультат.Вставить(КлиентHTTPПовтИсп.КодыСостояния().Перенаправления.ПеренаправлениеНаПостояннойОснове, Истина);
+ фРезультат.Вставить(КлиентHTTPПовтИсп.КодСостоянияПеренаправление(), Истина);
Возврат Новый ФиксированноеСоответствие(фРезультат);
КонецФункции
@@ -530,6 +548,15 @@
Возврат КлиентHTTPПовтИсп.ТипыMIME().text.xml;
КонецФункции
+// Возвращает MIME-тип application/xml
+//
+// Возвращаемое значение:
+// Строка - MIME-тип
+//
+Функция ТипMIMEApplicationXML() Экспорт
+ Возврат КлиентHTTPПовтИсп.ТипыMIME().application.xml;
+КонецФункции
+
// Возвращает MIME-тип text/html
//
// Возвращаемое значение:
@@ -703,7 +730,7 @@
Возврат Новый ФиксированноеСоответствие(фРезультат);
КонецФункции
-// Возвращает кодировку по умолчанию для HTTP-клиента
+// Возвращает кодировку по умолчанию для HTTP-клиента (UTF-8)
//
// Возвращаемое значение:
// Строка - кодировка
@@ -748,6 +775,15 @@
Возврат "UTF-32";
КонецФункции
+// Возвращает кодировку ISO-8859-1
+//
+// Возвращаемое значение:
+// Строка - кодировка
+//
+Функция КодировкаISO8859() Экспорт
+ Возврат "ISO-8859-1";
+КонецФункции
+
// Возвращает кодировку CESU-8
//
// Возвращаемое значение:
@@ -793,6 +829,105 @@
Возврат "cp866";
КонецФункции
+// Возвращает имя заголовка, содержащего хост сервера
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокХост() Экспорт
+ Возврат "Host";
+КонецФункции
+
+// Возвращает имя заголовка, содержащего характеристику пользовательского агента
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокАгентПользователя() Экспорт
+ Возврат "User-Agent";
+КонецФункции
+
+// Возвращает имя заголовка, содержащего тип контента
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокТипКонтента() Экспорт
+ Возврат "Content-Type";
+КонецФункции
+
+// Возвращает имя заголовка, содержащего размер контента
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокРазмерКонтента() Экспорт
+ Возврат "Content-Length";
+КонецФункции
+
+// Возвращает имя заголовка, содержащего данные аутентификации
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокТипАутентификации() Экспорт
+ Возврат "Authorization";
+КонецФункции
+
+// Возвращает имя заголовка, содержащего допустимые для клиента способы кодирования тела ответа (обычно, это алгоритмы сжатия)
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокДопустимыеСпособыКодированияОтвета() Экспорт
+ Возврат "Accept-Encoding";
+КонецФункции
+
+// Возвращает имя заголовка с Cookie
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокПеченье() Экспорт
+ Возврат "Cookie";
+КонецФункции
+
+// Возвращает имя заголовка ответа с Cookie
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокОтветаСПеченьем() Экспорт
+ Возврат "Set-Cookie";
+КонецФункции
+
+// Возвращает имя заголовка ответа, содержащего тип сжатия содержимого тела ответа
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокОтветаСжатиеТела() Экспорт
+ Возврат "Content-Encoding";
+КонецФункции
+
+// Возвращает имя заголовка ответа с URI перенаправления
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокОтветаПеренаправление() Экспорт
+ Возврат "Location";
+КонецФункции
+
+// Возвращает имя заголовка ответа с доступными типами аутентификации
+//
+// Возвращаемое значение:
+// Строка - имя заголовка
+//
+Функция ЗаголовокОтветаМетодыАутентификации() Экспорт
+ Возврат "WWW-Authenticate";
+КонецФункции
+
// Возвращает дату, называемую эпохой Unix
//
// Возвращаемое значение:
@@ -801,6 +936,112 @@
Функция ЭпохаUnix() Экспорт
Возврат Дата(1970, 1, 1);
КонецФункции
+
+// Возвращает AWS сервис S3
+//
+// Возвращаемое значение:
+// Строка - сервис
+//
+Функция СервисAWSS3() Экспорт
+ Возврат "s3";
+КонецФункции
+
+// Возвращает адресный перечень регионов AWS
+//
+// Возвращаемое значение:
+// ФиксированнаяСтруктура - ключи: константы регионов AWS
+//
+Функция РегионыAWS() Экспорт
+ фРезультат = Новый Структура;
+
+ Регионы = Новый Массив;
+ Регионы.Добавить("RU_1");
+ Регионы.Добавить("RU_MSK");
+ Регионы.Добавить("RU_CENTRAL1");
+ Регионы.Добавить("AF_SOUTH_1");
+ Регионы.Добавить("AP_EAST_1");
+ Регионы.Добавить("AP_NORTHEAST_1");
+ Регионы.Добавить("AP_NORTHEAST_2");
+ Регионы.Добавить("AP_NORTHEAST_3");
+ Регионы.Добавить("AP_SOUTH_1");
+ Регионы.Добавить("AP_SOUTH_2");
+ Регионы.Добавить("AP_SOUTHEAST_1");
+ Регионы.Добавить("AP_SOUTHEAST_2");
+ Регионы.Добавить("AP_SOUTHEAST_3");
+ Регионы.Добавить("AP_SOUTHEAST_4");
+ Регионы.Добавить("AWS_CN_GLOBAL");
+ Регионы.Добавить("AWS_GLOBAL");
+ Регионы.Добавить("AWS_ISO_B_GLOBAL");
+ Регионы.Добавить("AWS_ISO_GLOBAL");
+ Регионы.Добавить("AWS_US_GOV_GLOBAL");
+ Регионы.Добавить("CA_CENTRAL_1");
+ Регионы.Добавить("CN_NORTH_1");
+ Регионы.Добавить("CN_NORTHWEST_1");
+ Регионы.Добавить("EU_CENTRAL_1");
+ Регионы.Добавить("EU_CENTRAL_2");
+ Регионы.Добавить("EU_NORTH_1");
+ Регионы.Добавить("EU_SOUTH_1");
+ Регионы.Добавить("EU_SOUTH_2");
+ Регионы.Добавить("EU_WEST_1");
+ Регионы.Добавить("EU_WEST_2");
+ Регионы.Добавить("EU_WEST_3");
+ Регионы.Добавить("ME_CENTRAL_1");
+ Регионы.Добавить("ME_SOUTH_1");
+ Регионы.Добавить("SA_EAST_1");
+ Регионы.Добавить("US_EAST_1");
+ Регионы.Добавить("US_EAST_2");
+ Регионы.Добавить("US_GOV_EAST_1");
+ Регионы.Добавить("US_GOV_WEST_1");
+ Регионы.Добавить("US_ISO_EAST_1");
+ Регионы.Добавить("US_ISO_WEST_1");
+ Регионы.Добавить("US_ISOB_EAST_1");
+ Регионы.Добавить("US_WEST_1");
+ Регионы.Добавить("US_WEST_2");
+
+ Для Каждого Регион Из Регионы Цикл
+ фРезультат.Вставить(Регион, СтрЗаменить(НРег(Регион), "_", "-"));
+ КонецЦикла;
+
+ Возврат Новый ФиксированнаяСтруктура(фРезультат);
+КонецФункции
+
+#Область AWS_РЕГИОНЫ
+// Возвращает AWS регион по умолчанию (ru-1)
+//
+// Возвращаемое значение:
+// Строка - регион
+//
+Функция РегионAWSПоУмолчанию() Экспорт
+ Возврат КлиентHTTPПовтИсп.РегионAWSRu1();
+КонецФункции
+
+// Возвращает AWS регион ru-1
+//
+// Возвращаемое значение:
+// Строка - регион
+//
+Функция РегионAWSRu1() Экспорт
+ Возврат КлиентHTTPПовтИсп.РегионыAWS().RU_1;
+КонецФункции
+
+// Возвращает AWS регион ru-msk-1
+//
+// Возвращаемое значение:
+// Строка - регион
+//
+Функция РегионAWSRuMsk() Экспорт
+ Возврат КлиентHTTPПовтИсп.РегионыAWS().RU_MSK;
+КонецФункции
+
+// Возвращает AWS регион ru-central1
+//
+// Возвращаемое значение:
+// Строка - регион
+//
+Функция РегионAWSRuCentral1() Экспорт
+ Возврат КлиентHTTPПовтИсп.РегионыAWS().RU_CENTRAL1;
+КонецФункции
+#КонецОбласти
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
@@ -1131,7 +1372,18 @@
Возврат Новый ФиксированнаяСтруктура(фРезультат);
КонецФункции
-// Возвращает множество допустимых символов имени заголовка HTTP-запроса
+// Возвращает строку из допустимых символов имени заголовка HTTP-запроса
+//
+// Возвращаемое значение:
+// Строка - строка из допустимых символов имени заголовка
+//
+Функция ДопустимыеСимволыИмениЗаголовкаСтрокой() Экспорт
+ Буквы = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ Возврат Буквы + НРег(Буквы) + "0123456789!#$%&'*+-.^_`|~";
+КонецФункции
+
+// (УСТАРЕЛО) Возвращает множество допустимых символов имени заголовка HTTP-запроса
//
// Возвращаемое значение:
// ФиксированноеСоответствие - служебный словарь допустимых символов имени заголовка
@@ -1139,8 +1391,7 @@
Функция ДопустимыеСимволыИмениЗаголовка() Экспорт
фРезультат = Новый Соответствие;
- Буквы = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- ДопустимыеСимволы = Буквы + НРег(Буквы) + "0123456789!#$%&'*+-.^_`|~";
+ ДопустимыеСимволы = КлиентHTTPПовтИсп.ДопустимыеСимволыИмениЗаголовкаСтрокой();
Для я = 1 По СтрДлина(ДопустимыеСимволы) Цикл
фРезультат.Вставить(Сред(ДопустимыеСимволы, я, 1), Истина);
diff --git "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\241\320\273\321\203\320\266\320\265\320\261\320\275\321\213\320\271/Ext/Module.bsl" "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\241\320\273\321\203\320\266\320\265\320\261\320\275\321\213\320\271/Ext/Module.bsl"
index b0c732c..6f5cfc8 100644
--- "a/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\241\320\273\321\203\320\266\320\265\320\261\320\275\321\213\320\271/Ext/Module.bsl"
+++ "b/src/v1/CommonModules/\320\232\320\273\320\270\320\265\320\275\321\202HTTP\320\241\320\273\321\203\320\266\320\265\320\261\320\275\321\213\320\271/Ext/Module.bsl"
@@ -111,6 +111,7 @@
КонецФункции
// Возвращает текстовое представление даты RFC 1123
+// Date: Tue, 15-Nov-1994 08:12:31 GMT
//
// Параметры:
// Дата - Дата - конвертируемое значение
@@ -126,6 +127,23 @@
);
КонецФункции
+// Возвращает текстовое представление даты RFC 7231 (7.1.1.2)
+// Date: Tue, 15 Nov 1994 08:12:31 GMT
+//
+// Параметры:
+// Дата - Дата - конвертируемое значение
+//
+// Возвращаемое значение:
+// Строка - дата формата RFC 7231 (7.1.1.2)
+//
+Функция ДатаВHTTP7231(Знач Дата) Экспорт
+ Возврат СтрШаблон(
+ Формат(Дата, "ДФ='""%1"", дд ""%2"" гггг Ч:м:с ""GMT""'"),
+ ДеньНеделиНаАнглийском(Дата),
+ МесяцНаАнглийском(Дата)
+ );
+КонецФункции
+
// Возвращает преобразованный в ACE-последовательность IDN
//
// Параметры:
@@ -137,6 +155,30 @@
Функция НормализованныйАдресСервера(Знач АдресСервера) Экспорт
Возврат КодироватьАдресСервера(НРег(СокрЛП(АдресСервера)));
КонецФункции
+
+// Возвращает имя параметра запроса с экранированием
+//
+// Параметры:
+// Имя - Строка - имя параметра запроса
+//
+// Возвращаемое значение:
+// Строка - экранированное имя параметра запроса
+//
+Функция ФорматированноеИмяПараметраЗапроса(Знач Имя) Экспорт
+ Возврат СтрЗаменить(ФорматированноеЗначениеПараметраЗапроса(Имя), "=", "%3D");
+КонецФункции
+
+// Возвращает значение параметра запроса с экранированием
+//
+// Параметры:
+// Значение - Строка - значение параметра запроса
+//
+// Возвращаемое значение:
+// Строка - экранированное значение параметра запроса
+//
+Функция ФорматированноеЗначениеПараметраЗапроса(Знач Значение) Экспорт
+ Возврат СтрЗаменить(СтрЗаменить(СтрЗаменить(СокрЛП(Значение), Символы.ПС, ""), "#", "%23"), "&", "%26");
+КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
diff --git a/src/v1/Configuration.xml b/src/v1/Configuration.xml
index 9a9ca3a..ce0a2dc 100644
--- a/src/v1/Configuration.xml
+++ b/src/v1/Configuration.xml
@@ -49,7 +49,7 @@