Работа с внешними API через протокол HTTP — одна из самых частых задач современного разработчика 1С. Однако часто мы сталкиваемся с тем, что старые проверенные методы через COM-объект WinHttp.WinHttpRequest.5.1 начинают вести себя непредсказуемо: возникают лаги при инициализации, зависают методы установки таймаутов, а при попытке перейти на штатные механизмы платформы (HTTPСоединение) внезапно возникают ошибки 502 Proxy Error или Failure when receiving data from the peer. В этой статье мы подробно разберем, почему это происходит и как правильно настроить обмен данными.
Когда мы вызываем метод SetTimeouts или Open, и выполнение кода «замирает» на несколько секунд, хотя данные еще не передаются, проблема обычно кроется не в сетевом коде 1С, а в механизмах самой операционной системы Windows, которые использует этот COM-объект.
Рассмотрим основные причины задержек:
WinHttp пытается автоматически определить настройки прокси-сервера через протокол WPAD. Если в вашей локальной сети этот протокол настроен некорректно или DNS-сервер долго отвечает на специфические запросы, объект будет ожидать ответа системы, что визуально выглядит как зависание 1С.WinHttp может пытаться связаться с серверами удостоверяющих центров для проверки валидности сертификата. В условиях закрытых корпоративных сетей без прямого доступа в интернет это вызывает значительные задержки.USR1CV8). У этой записи зачастую нет загруженного профиля пользователя, из-за чего системные кэши сетевых настроек недоступны, и WinHttp вынужден каждый раз инициализировать окружение «с нуля».Чтобы минимизировать лаги в WinHttp, можно попробовать принудительно отключить использование прокси, если он не нужен для данного соединения. Проанализируем пример кода:
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// Отключаем использование прокси (0 - WinHttpProxySet_NoProxy)
WinHttp.SetProxy(0);
Таймаут = 1000;
WinHttp.SetTimeouts(Таймаут, Таймаут, Таймаут, Таймаут);
Многие разработчики при возникновении проблем с COM-объектами решают переписать код на штатные объекты 1С: HTTPСоединение и HTTPЗапрос. Однако здесь их часто поджидает ошибка 502 Proxy Error. The ISA Server denied the specified Uniform Resource Locator (URL). (12202). Выясним причину этой ошибки.
Проблема чаще всего заключается в том, как именно формируется объект HTTPСоединение. В отличие от WinHttp, где полный URL передается в метод Open, в 1С адрес ресурса жестко разделен на Сервер и Путь к ресурсу.
Посмотрим на типичную ошибку:
// ОШИБОЧНЫЙ ВАРИАНТ
АдресРесурса = "http://api.myservice.ru/v1/getData";
// Если передать весь путь в конструктор соединения, прокси-сервер (например, ISA Server) выдаст 502
Соединение = Новый HTTPСоединение(АдресРесурса);
Запрос = Новый HTTPЗапрос("/");
Разберем правильный вариант реализации:
// ПРАВИЛЬНЫЙ ВАРИАНТ
Сервер = "api.myservice.ru";
ПутьКРесурсу = "/v1/getData";
// Указываем только имя сервера (хост)
Соединение = Новый HTTPСоединение(Сервер, , Пользователь, Пароль, , Таймаут);
ЗаголовокHTTP = Новый Соответствие();
ЗаголовокHTTP.Вставить("Content-Type", "text/xml; charset=utf-8");
// Путь к ресурсу передается только в HTTPЗапрос
Запрос = Новый HTTPЗапрос(ПутьКРесурсу, ЗаголовокHTTP);
Запрос.УстановитьТелоИзСтроки(ДанныеЗапроса, КодировкаТекста.UTF8);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Важно помнить, что прокси-серверы, такие как Microsoft ISA Server или Forefront TMG, крайне чувствительны к заголовку Host и корректности формирования URI. Если вы передадите протокол http:// внутри параметра "Сервер", прокси воспримет это как некорректный запрос.
Если после исправления структуры URL вы столкнулись с ошибкой Failure when receiving data from the peer, это сигнализирует о проблемах на этапе SSL-рукопожатия (Handshake) или при получении данных через защищенный канал. Начиная с версии 8.3.14, 1С использует библиотеку libcurl, которая более строго следует стандартам безопасности, чем старый WinHttp.
Проанализируем шаги для решения:
HTTPСоединение с современными сайтами.https в 1С необходимо использовать объект ЗащищенноеСоединениеOpenSSL. Посмотрим на пример:
Защита = Новый ЗащищенноеСоединениеOpenSSL(Новый СертификатКлиентаWindows(), Новый СертификатыУдостоверяющихЦентровWindows());
// Передаем объект защиты в конструктор соединения
Соединение = Новый HTTPСоединение(Сервер, 443, Пользователь, Пароль, , Таймаут, Защита);
Если программный код кажется верным, но сервер всё равно возвращает ошибку, воспользуемся методом сравнения «как делает WinHttp» и «как делает HTTPСоединение». Для этого идеально подходит инструмент Fiddler.
Алгоритм диагностики:
WinHttp (который работает).HTTPСоединение (который выдает ошибку).User-Agent, Accept, Connection. Часто прокси-серверы блокируют запросы без заголовка User-Agent или со специфическим агентом 1С.Для подмены заголовка в 1С используйте метод Вставить объекта Соответствие, который передается в HTTPЗапрос:
ЗаголовокHTTP.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
Подведем итоги нашего исследования. Для стабильной работы с HTTP в 1С 8.3 следует придерживаться следующих правил:
WinHttp.WinHttpRequest в новом коде, так как его поведение сильно зависит от настроек ОС и профиля пользователя.HTTPСоединение всегда четко разделяйте адрес сервера и путь к ресурсу (никаких http:// в имени сервера).Content-Type и User-Agent.ИнтернетПрокси, явно указывая настройки для протоколов http и https.Следуя этим шагам, мы сможем построить надежный и быстрый механизм обмена данными, лишенный внезапных зависаний и ошибок авторизации на прокси-серверах.