ЗагрузитьСодержимоеИзИнтернет (БСП)

Автор: 1С
ОбщийМодуль.ИнтернетПоддержкаПользователей
БСП

Загрузить содержимое из интернет. Загружает содержимое из Интернет по протоколу HTTP(S)

// Загружает содержимое из Интернет по протоколу HTTP(S)
// с использованием методов GET, POST или PUT.
//
Функция ЗагрузитьСодержимоеИзИнтернет(
	Знач URL,
	Знач Логин = Неопределено,
	Знач Пароль = Неопределено,
	ДопПараметры = Неопределено) Экспорт

	Результат = Новый Структура;
	Результат.Вставить("КодОшибки"         , "");
	Результат.Вставить("СообщениеОбОшибке" , "");
	Результат.Вставить("ИнформацияОбОшибке", "");
	Результат.Вставить("Содержимое"        , Неопределено);
	Результат.Вставить("КодСостояния"      , 0);
	Результат.Вставить("ФорматОтвета"      , 0);

	// Формат ответа: 0 - имя файла ответа, 1 - как строка, 2 - как двоичные данные.
	// Метод: "GET", "POST" или "PUT".
	// ДанныеДляОбработки: данные, передаваемые методом POST.
	// ФорматДанныхДляОбработки: 0 - имя файла, 1 как строка, 2 - как двоичные данные.
	// Заголовки - заголовки запроса.
	ПараметрыПолучения = Новый Структура;
	ПараметрыПолучения.Вставить("ФорматОтвета"            , 0);
	ПараметрыПолучения.Вставить("Метод"                   , "GET");
	ПараметрыПолучения.Вставить("ДанныеДляОбработки"      , Неопределено);
	ПараметрыПолучения.Вставить("ФорматДанныхДляОбработки", 0);
	ПараметрыПолучения.Вставить("Заголовки"               , Неопределено);
	ПараметрыПолучения.Вставить("ИмяФайлаОтвета"          , Неопределено);
	ПараметрыПолучения.Вставить("Таймаут"                 , -1);
	ПараметрыПолучения.Вставить("НастройкиПрокси"         , Неопределено);
	
	Если ДопПараметры <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(ПараметрыПолучения, ДопПараметры);
	КонецЕсли;
	
	Если ПараметрыПолучения.Таймаут = -1 Тогда
		// Таймаут по умолчанию.
		ПараметрыПолучения.Таймаут = 30;
	КонецЕсли;
	
	Результат.ФорматОтвета = ПараметрыПолучения.ФорматОтвета;
	
	КоличествоПеренаправлений  = 0;
	МаксКолвоПеренаправлений   = 7;
	Перенаправления            = Новый Массив;
	ВыполненныеПеренаправления = Новый Соответствие;
	ПроксиПоСхемам             = Новый Соответствие;
	ЗащищенноеСоединениеКэш    = Неопределено;
	
	URLДляПолучения = URL;
	HTTPЗапрос = Новый HTTPЗапрос;
	Если ПараметрыПолучения.Заголовки <> Неопределено Тогда
		HTTPЗапрос.Заголовки = ПараметрыПолучения.Заголовки;
	КонецЕсли;
	ТелоУстановлено = Ложь;
	Ответ = Неопределено;
	Пока КоличествоПеренаправлений < МаксКолвоПеренаправлений Цикл

		СтруктураURI = ОбщегоНазначенияКлиентСервер.СтруктураURI(URLДляПолучения);
		Если СтруктураURI.Схема <> "https" Тогда
			ЗащищенноеСоединение = Неопределено;
		Иначе
			Если ЗащищенноеСоединениеКэш = Неопределено Тогда
				ЗащищенноеСоединениеКэш = ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение(
					Неопределено,
					Новый СертификатыУдостоверяющихЦентровОС);
			КонецЕсли;
			ЗащищенноеСоединение = ЗащищенноеСоединениеКэш;
		КонецЕсли;

		Если НЕ ПустаяСтрока(СтруктураURI.Логин) Тогда
			ЛогинДляПолучения  = СтруктураURI.Логин;
			ПарольДляПолучения = СтруктураURI.Пароль;
		Иначе
			ЛогинДляПолучения  = Логин;
			ПарольДляПолучения = Пароль;
		КонецЕсли;

		Если СтруктураURI.Порт = Неопределено ИЛИ ПустаяСтрока(СтруктураURI.Порт) Тогда
			Порт = ?(ЗащищенноеСоединение = Неопределено, 80, 443);
		Иначе
			Порт = Число(СтруктураURI.Порт);
		КонецЕсли;

		Прокси = ПроксиПоСхемам.Получить(СтруктураURI.Схема);
		Если Прокси = Неопределено Тогда
			Если ПараметрыПолучения.НастройкиПрокси = Неопределено Тогда
				Прокси = ПолучениеФайловИзИнтернета.ПолучитьПрокси(СтруктураURI.Схема);
			Иначе
				Прокси = СформироватьИнтернетПрокси(ПараметрыПолучения.НастройкиПрокси, СтруктураURI.Схема);
			КонецЕсли;
			ПроксиПоСхемам.Вставить(СтруктураURI.Схема, Прокси);
		КонецЕсли;

		Соединение = Новый HTTPСоединение(
			СтруктураURI.Хост,
			Порт,
			ЛогинДляПолучения,
			ПарольДляПолучения,
			Прокси,
			ПараметрыПолучения.Таймаут,
			ЗащищенноеСоединение);

		Попытка

			HTTPЗапрос.АдресРесурса = СтруктураURI.ПутьНаСервере;

			Если ПараметрыПолучения.Метод = "GET" Тогда
				Ответ = Соединение.Получить(HTTPЗапрос, ПараметрыПолучения.ИмяФайлаОтвета);
			ИначеЕсли ПараметрыПолучения.Метод = "HEAD" Тогда
				Ответ = Соединение.ПолучитьЗаголовки(HTTPЗапрос);
			Иначе
			
				Если НЕ ТелоУстановлено Тогда

					Если ПараметрыПолучения.ДанныеДляОбработки <> Неопределено Тогда

						Если ПараметрыПолучения.ФорматДанныхДляОбработки = 0 Тогда

							HTTPЗапрос.УстановитьИмяФайлаТела(ПараметрыПолучения.ДанныеДляОбработки);

						ИначеЕсли ПараметрыПолучения.ФорматДанныхДляОбработки = 1 Тогда

							HTTPЗапрос.УстановитьТелоИзСтроки(ПараметрыПолучения.ДанныеДляОбработки);

						Иначе

							HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ПараметрыПолучения.ДанныеДляОбработки);

						КонецЕсли;

					КонецЕсли;

					ТелоУстановлено = Истина;

				КонецЕсли;

				Если ПараметрыПолучения.Метод = "PUT" Тогда
					Ответ = Соединение.Записать(HTTPЗапрос);
				Иначе
					// POST
					Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос, ПараметрыПолучения.ИмяФайлаОтвета);
				КонецЕсли;

			КонецЕсли;

		Исключение
			
			ПредставлениеОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
			ПодробноеОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Не удалось загрузить содержимое (%1). %2'"),
				URL,
				ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
			
			// Диагностика соединения с ресурсом.
			Попытка
				
				РезультатДиагностики = ПолучениеФайловИзИнтернета.ДиагностикаСоединения(URL);
				ОписаниеРезультатаДиагностики = НСтр("ru = 'Результаты диагностики соединения:'")
					+ Символы.ПС + РезультатДиагностики.ОписаниеОшибки;
				
			Исключение
				
				ОписаниеРезультатаДиагностики = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Не удалось выполнить диагностику соединения. %1'"),
					ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
				
			КонецПопытки;
			
			УстановитьОписаниеОшибки(
				Результат,
				"ConnectError",
				ПредставлениеОшибки,
				ПодробноеОписаниеОшибки + Символы.ПС + ОписаниеРезультатаДиагностики,
				Перенаправления);
			Возврат Результат;
			
		КонецПопытки;

		Результат.КодСостояния = Ответ.КодСостояния;

		Если Ответ.КодСостояния = 301 // 301 Moved Permanently
			ИЛИ Ответ.КодСостояния = 302 // 302 Found, 302 Moved Temporarily
			ИЛИ Ответ.КодСостояния = 303 // 303 See Other by GET
			ИЛИ Ответ.КодСостояния = 307 Тогда // 307 Temporary Redirect

			КоличествоПеренаправлений = КоличествоПеренаправлений + 1;

			Если КоличествоПеренаправлений > МаксКолвоПеренаправлений Тогда
				УстановитьОписаниеОшибки(
					Результат,
					"ServerError",
					НСтр("ru = 'Превышено количество перенаправлений.'"),
					СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'Ошибка сервера при получении файла (%1). Превышено количество перенаправлений (%2).'"),
						URL,
						МаксКолвоПеренаправлений),
					Перенаправления);
				Возврат Результат;
			Иначе
				Location = Ответ.Заголовки.Получить("Location");
				Если Location = Неопределено Тогда
					УстановитьОписаниеОшибки(
						Результат,
						"ServerError",
						НСтр("ru = 'Некорректное перенаправление.'"),
						СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
							НСтр("ru = 'Ошибка сервера (%1) при получении файла (%2). Некорректное перенаправление, отсутствует HTTP-заголовок ответа ""Location"".'"),
							Ответ.КодСостояния,
							URL),
						Перенаправления);
					Возврат Результат;
				Иначе
					Location = СокрЛП(Location);
					Если ПустаяСтрока(Location) Тогда
						УстановитьОписаниеОшибки(
							Результат,
							"ServerError",
							НСтр("ru = 'Некорректное перенаправление.'"),
							СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
								НСтр("ru = 'Ошибка сервера (%1) при получении файла (%2). Некорректное перенаправление, пустой HTTP-заголовок ответа ""Location"".'"),
								Ответ.КодСостояния,
								URL),
							Перенаправления);
						Возврат Результат;
					КонецЕсли;

					Если ВыполненныеПеренаправления.Получить(Location) <> Неопределено Тогда
						УстановитьОписаниеОшибки(
							Результат,
							"ServerError",
							НСтр("ru = 'Циклическое перенаправление.'"),
							СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
								НСтр("ru = 'Ошибка сервера (%1) при получении файла (%2). Циклическое перенаправление (%3).'"),
								Ответ.КодСостояния,
								URL,
								Location),
							Перенаправления);
						Возврат Результат;
					КонецЕсли;

					ВыполненныеПеренаправления.Вставить(Location, Истина);
					URLДляПолучения = Location;

					Перенаправления.Добавить(Строка(Ответ.КодСостояния) + ": " + Location);

				КонецЕсли;
				
			КонецЕсли;

		Иначе

			Прервать;

		КонецЕсли;

	КонецЦикла;

	Если ПараметрыПолучения.ФорматОтвета = 0 Тогда
		Результат.Содержимое = Ответ.ПолучитьИмяФайлаТела();
	ИначеЕсли ПараметрыПолучения.ФорматОтвета = 1 Тогда
		Результат.Содержимое = Ответ.ПолучитьТелоКакСтроку();
	ИначеЕсли ПараметрыПолучения.ФорматОтвета = 2 Тогда
		Результат.Содержимое = Ответ.ПолучитьТелоКакДвоичныеДанные();
	Иначе
		Результат.Содержимое = Ответ;
	КонецЕсли;
	
	// Обработка ответа
	Если Ответ.КодСостояния < 200 Или Ответ.КодСостояния >= 300 Тогда

		// Анализ ошибки
		Если Ответ.КодСостояния = 407 Тогда

			// Ошибка подключения - не пройдена аутентификация на прокси-сервере.
			УстановитьОписаниеОшибки(
				Результат,
				"ConnectError",
				НСтр("ru = 'Ошибка аутентификации на прокси-сервере.'"),
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка клиента (%1) при выполнении запроса к ресурсу (%2).
						|Тело ответа: %3'"),
					Ответ.КодСостояния,
					URL,
					Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
				Перенаправления);

		ИначеЕсли Ответ.КодСостояния < 200
			ИЛИ Ответ.КодСостояния >= 300
			И Ответ.КодСостояния < 400 Тогда

			// Формат ответа сервера не поддерживается.
			УстановитьОписаниеОшибки(
				Результат,
				"ServerError",
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Некорректный ответ сервера (%1).'"),
					Ответ.КодСостояния),
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка сервера при получении файла (%1). Некорректный (неподдерживаемый) ответ (%2).
						|Тело ответа: %3'"),
					URL,
					Ответ.КодСостояния,
					Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
				Перенаправления);

		ИначеЕсли Ответ.КодСостояния >= 400 И Ответ.КодСостояния < 500 Тогда

			// Ошибка клиентской части - некорректный запрос.
			УстановитьОписаниеОшибки(
				Результат,
				"ClientError",
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка (%1) при выполнении запроса к ресурсу.'"),
					Строка(Ответ.КодСостояния)),
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка клиента (%1) при выполнении запроса к ресурсу (%2).
						|Тело ответа: %3'"),
					Ответ.КодСостояния,
					URL,
					Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
				Перенаправления);

		Иначе

			// Ошибка сервера - 5хх
			УстановитьОписаниеОшибки(
				Результат,
				"ServerError",
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Код ошибки: %1.'"),
					Строка(Ответ.КодСостояния)),
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Ошибка сервера (%1) при обработке запроса к ресурсу (%2).
						|Тело ответа: %3'"),
					Ответ.КодСостояния,
					URL,
					Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
				Перенаправления);

		КонецЕсли;

		ДобавитьСписокПеренаправленийКИнформацииОбОшибке(
			Результат.ИнформацияОбОшибке,
			Перенаправления);

	КонецЕсли;

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

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

///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

Рекомендации

Похожие публикации

Загрузить (БСП)

ОтфильтроватьСодержимоеТекстаHTML (БСП)

ОтключитьНебезопасноеСодержимое (БСП)

СодержимоеТегаHTML (БСП)

TurboConf - расширение Конфигуратора 1С