gifts2017

Универсальный механизм общения с внешним миром. HTTPЗапрос POST / GET / JSON

Опубликовал _ Ya, Ti, On, Ona, Vmeste celaya strana (agent00mouse) в раздел Программирование - Практика программирования

Умеет 1С общаться с внешним миром. Мне кажется, не совсем удобно пользоваться тем функционалом, что дали нам разработчики платформы. И решил тогда (копируя из раза в раз однотипные куски кода) написать себе универсальный велосипед.
Что он умеет:
Отправлять запросы GET - просто строка с адресом
Отправлять запросы POST - адрес + строка(ки) содержимого
Преобразовать отправляемые данные формата JSON
Принимать данные в строку, или через файл. Если данных много, но всё равно потом записывать в переменную содержимое файла.
Принимать бинарные/картинки. Принимает, но отдаёт их строкой. Нужно взять напильник и подточить функцию.

Пользовать начиная с платформы - 8.3.6

Решение:

Функция ВыполнитьЗапрос(Параметры) Экспорт
	
	Ответ = Новый Структура("Код, ДанныеОтвета",0,"");
	//Получим хост
	АдресДл = Параметры.УРЛ;
	АдресДл = СтрЗаменить(АдресДл, "https://" ,"");  
	АдресДл = СтрЗаменить(АдресДл, "http://" ,"");  
	индексСлеша  = Найти(АдресДл, "/");
	ХОСТ = АдресДл;
	Если индексСлеша > 0 Тогда
		ХОСТ = Сред(АдресДл, 1 ,индексСлеша - 1);
	КонецЕсли;
	
	// вычислить строку URL
	длинаСтроки = СтрДлина(АдресДл);
	Ресурс = "/" + Прав(АдресДл, длинаСтроки -  индексСлеша);
	
	Порт        = 80;  ssl = Неопределено; 
	Если Параметры.Свойство("Логин") Тогда 
	    Если Найти(ВРег(Параметры.УРЛ), ВРег("https")) > 0 Тогда 
	        Порт = 443;
	        ssl = Новый ЗащищенноеСоединениеOpenSSL( неопределено, неопределено ); 
		КонецЕсли;
		HTTPСоединение =  Новый HTTPСоединение(ХОСТ, Порт, 
		Параметры.Логин,  Параметры.Пароль,,, ssl); 
	Иначе
		HTTPСоединение =  Новый HTTPСоединение(ХОСТ,,,,,);
	КонецЕсли;
	
	
	//ФайлЗапроса = ПолучитьИмяВременногоФайла();    
	// Преобразуем типы платформы в JSON  
	ТелоЗапроса = Истина;
	Если Параметры.Свойство("Тело") Тогда
		ТелоЗапроса = Параметры.Тело; 
	ИначеЕсли Параметры.Свойство("ТелоJSon") Тогда
		СтрокаJSON = Новый ЗаписьJSON; СтрокаJSON.УстановитьСтроку();
		ЗаписатьJSON(СтрокаJSON, Параметры.ТелоJSon);
		ТелоЗапроса = СтрокаJSON.Закрыть(); 
	КонецЕсли;
		
	
	КодСостояния = 0;
	ОтветСервера = "";
	
	ЗаголовокHTTP = Новый Соответствие();
	ЗаголовокHTTP.Вставить("Host", Хост);
	Если Параметры.Свойство("Заголовок") Тогда
		Для Каждого ЭлементЗ из Параметры.Заголовок Цикл 
			ЗаголовокHTTP.Вставить(ЭлементЗ.Парам, ЭлементЗ.Знч);
		КонецЦикла;	
	КонецЕсли;
	
	
	Попытка
		ФайлОтвета	= Неопределено;
		Если (Параметры.Свойство("ЧерезФайл")) Тогда 
			ФайлОтвета	= ПолучитьИмяВременногоФайла(Параметры.ЧерезФайл);	
		КонецЕсли;
		
		HTTPЗапрос	= Новый HTTPЗапрос(Ресурс, ЗаголовокHTTP);
		HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8);
		
		Если ((Параметры.Свойство("Способ")) и (Врег(Параметры.Способ) = "POST"))
				или
			(Параметры.Свойство("Тело")) или (Параметры.Свойство("ТелоJSon"))
			Тогда 
				Если (Параметры.Свойство("ЧерезФайл")) Тогда 
					HTTPОтвет	= HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос, ФайлОтвета);
				Иначе
					HTTPОтвет	= HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
				КонецЕсли;
		Иначе
			HTTPОтвет	= HTTPСоединение.Получить(HTTPЗапрос);
		КонецЕсли;
		
		ДанныеОтвета = "";
		Ответ.Вставить("Код", HTTPОтвет.КодСостояния);
		Если Ответ.Код = 200 Тогда
			Если (Параметры.Свойство("ЧерезФайл")) Тогда 
				Если Параметры.Свойство("ОтветJSON") Тогда
					Чтение = Новый ЧтениеJSON;
					Чтение.ОткрытьФайл(ФайлОтвета);
					ДанныеОтвета = ПрочитатьJSON(Чтение, Ложь);
					Чтение.Закрыть();
				Иначе
					Файл = Новый ЧтениеТекста(ФайлОтвета);
					ДанныеОтвета = Файл.Прочитать();
					Файл.Закрыть();
				КонецЕсли;
				Попытка
					УдалитьФайлы(ФайлОтвета);
				Исключение
				КонецПопытки;
			Иначе
				Если Параметры.Свойство("ОтветJSON") Тогда
					ДанныеОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
					Чтение = Новый ЧтениеJSON;
					Чтение.УстановитьСтроку(ДанныеОтвета);
					ДанныеОтвета = ПрочитатьJSON(Чтение, Ложь);
					Чтение.Закрыть();
				Иначе
					ДанныеОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
				КонецЕсли;
			КонецЕсли;
			
			
		КонецЕсли;
		
		Ответ.Вставить("ДанныеОтвета", ДанныеОтвета);
	Исключение
		Сообщить("Не удалось установить соединение с сервером :" 
		+ Символы.ПС + ИнформацияОбОшибке().Описание, СтатусСообщения.Важное);
	КонецПопытки;
	
	Возврат Ответ;
	
КонецФункции

 

Пример вызова:

параметры:

Заголовок - Если нужен хитрый заголовок, указываем свои параметры, см. ниже.

УРЛ - Полный путь к ресурсу

Логин/Пароль - Пользовать парой, указывает на работут через basic authentication

ОтветJSON - Просим преобразовать ответ в струкруты, массивы, объекты 1С

ЧерезФайл - Указывает принять запрос через файл. (для большого ответа. Например последующее чтение JSON)

 

		Заголовок		= Новый Массив();
		Заголовок.Добавить( Новый Структура("Парам, Знч",	"Content-Type",		"application/json") );
		Заголовок.Добавить( Новый Структура("Парам, Знч",	"Accept",		"application/json; utf-8;") );
		Заголовок.Добавить( Новый Структура("Парам, Знч",	"Accept-Charset",	"utf-8;") );
		
		Парам = новый Структура();
		Парам.Вставить("Заголовок", Заголовок);
		Парам.Вставить("УРЛ", "https://www.google.ru"+"/?gfe_rd=cr&ei=L3ByV96dD-KWwAPrloEg&gws_rd=ssl#newwindow=1&q=Василий Алибабаевич");
		
		ОтветСодержимое = ВыполнитьЗапрос(Парам);

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Имя Фамилия (neyasytyf) 29.06.16 08:24
2. _ Ya, Ti, On, Ona, Vmeste celaya strana (agent00mouse) 29.06.16 08:39
(1) neyasytyf, Наверняка 8.3. Значит со временем функция мутировала. Спасибо.
3. 123 321 (Lenten) 30.06.16 17:35
1) Чето у меня ругается. Платформа 1С:Предприятие 8.3 (8.3.5.1517)

{Форма.Форма.Форма(55,28)}: Тип не определен (ЗаписьJSON)
СтрокаJSON = Новый <<?>>ЗаписьJSON; СтрокаJSON.УстановитьСтроку(); (Проверка: Толстый клиент (обычное приложение))
{Форма.Форма.Форма(100,36)}: Тип не определен (ЧтениеJSON)
Чтение = Новый <<?>>ЧтениеJSON; (Проверка: Толстый клиент (обычное приложение))
{Форма.Форма.Форма(116,36)}: Тип не определен (ЧтениеJSON)
Чтение = Новый <<?>>ЧтениеJSON; (Проверка: Толстый клиент (обычное приложение))
2) А что будет логином и паролем в случае с гуглом. Я вообще в этом не секу )
4. _ Ya, Ti, On, Ona, Vmeste celaya strana (agent00mouse) 30.06.16 20:24
(3) Lenten, Логин и пароль были вырваны из контекста, просто для примера.
ЧтениеJSON - появился в платформе начиная с релиза 8.3.6...
5. Евгений Колтович (depresnjak) 05.07.16 00:58
Как по мне, то тема https и ssl раскрыта не полностью.
6. _ Ya, Ti, On, Ona, Vmeste celaya strana (agent00mouse) 05.07.16 09:52
(5) depresnjak, Согласен, Мне базовой уровень авторизации пока было достаточно. Есть наработка по авторизации через сертификат, Всё выльется в небольшую библиотеку.
Будут просьбы расширить функционал, постараюсь дописать.
7. Сергей Толмачев (sss999) 11.07.16 23:01
Можешь подсказать по коду?
8. _ Ya, Ti, On, Ona, Vmeste celaya strana (agent00mouse) 12.07.16 08:00
9. Владимир Гусев (adhocprog) 03.08.16 15:48
Спасибо! Полезный материал )
10. Евгений Маляров (unpete) 08.08.16 15:56
Порты 80 и 443, наверное, следует задавать только в том случае, если они не указаны в url.
Ваш код отработает с ошибкой для запроса вида https://mysite.com:8359/data.json#private
11. _ Ya, Ti, On, Ona, Vmeste celaya strana (agent00mouse) 10.08.16 21:13
(10) unpete, (10) unpete, Дельное замечание. поправлю.
12. Антон Степанов (Stepa86) 01.09.16 12:50
В УП и видимо в других конфах со встроенной библиотекой интернет-поддержки пользователей есть метод ИнтернетПоддержкаПользователейКлиентСервер.ЗагрузитьСодержимоеИзИнтернет(
Знач URL,
Знач Логин = Неопределено,
Знач Пароль = Неопределено,
ДопПараметры = Неопределено) Экспорт
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа