При разработке интеграций и вызове собственных HTTP-сервисов разработчики часто сталкиваются с ситуацией, когда один и тот же адрес успешно открывается через веб-браузер, но программный код на платформе 1С:Предприятие завершается с исключением: Ошибка работы с Интернет: Не могу установить соединение. Разберем по шагам, почему возникает эта сетевая неполадка, как локализовать ее источник и как правильно писать код отправки HTTP-запросов.
Выясним главную причину, с которой столкнулся автор темы. Веб-браузер (например, Chrome или Edge) обычно уже добавлен в правила исключений брандмауэра Windows или стороннего антивирусного ПО, поэтому его сетевые запросы к локальному компьютеру пропускаются без ограничений. Однако исполняемые файлы платформы 1С — 1cv8c.exe (тонкий клиент), 1cv8.exe (толстый клиент) или ragent.exe / rphost.exe (серверные службы) — могут не иметь разрешения на сетевую активность.
Для исправления ситуации выполним следующие действия:
Проанализируем работу сетевого стека операционной системы. Имя узла localhost в современных ОС по умолчанию сопоставляется с IPv6-адресом ::1. Веб-сервер (Apache HTTP Server или Microsoft IIS), на котором опубликован сервис 1С, может быть сконфигурирован слушать только стек IPv4 (адрес 127.0.0.1). В этом случае попытка 1С обратиться по имени localhost приведет к невозможности открыть TCP-сокет.
Рассмотрим, как гарантировать подключение по протоколу IPv4. Вместо имени узла в конструкторе соединения следует явно указывать IP-адрес:
// Явное указание локального IPv4-адреса
Сервер = "127.0.0.1";
Порт = 80; // Если используется нестандартный порт, указываем его явно
Соединение = Новый HTTPСоединение(Сервер, Порт, "web", "777");
Разберем архитектурную особенность клиент-серверной 1С. Если вызов объекта HTTPСоединение выполняется в серверной процедуре (на стороне &НаСервере, в общем модуле с признаком выполнения на сервере, в фоновом или регламентном задании), то адрес localhost или 127.0.0.1 будет указывать на сервер, где работает кластер 1С, а не на компьютер пользователя. Если веб-сервер развернут на отдельной машине, платформа попытается найти сервис локально на сервере приложений и вернет ошибку отсутствия соединения. В серверном коде необходимо указывать реальное сетевое доменное имя или сетевой IP-адрес сервера с веб-публикацией.
Платформа 1С может автоматически подтягивать настройки прокси-сервера операционной системы. Если в сети используется корпоративный прокси, запрос к локальному сервису может уйти во внешнюю сеть, где прокси-сервер просто отклонит запрос к localhost. Чтобы избежать такого поведения, создадим объект ИнтернетПрокси и настроим список исключений:
Прокси = Новый ИнтернетПрокси;
Прокси.НеИспользоватьПроксиДляАдресов = "localhost, 127.0.0.1";
Прокси.НеИспользоватьПроксиДляЛокальныхСетей = Истина;
Соединение = Новый HTTPСоединение(
"127.0.0.1", // Сервер
80, // Порт
"web", // Пользователь
"777", // Пароль
Прокси // Явно переданный прокси с исключениями
);
Посмотрим на путь запроса, приведенный в вопросе: /ppmen/hs/WebExchange/888/Тестовые данные. Стандарт RFC 3986 не допускает передачу кириллических символов и неэкранированных пробелов напрямую в строке пути запроса. Веб-браузер автоматически преобразует такие символы в формат Percent-Encoding (процентное кодирование), однако объект HTTPЗапрос платформы 1С отправляет строку в веб-сервер без фонового преобразования, что гарантированно приведет к ошибкам обработки.
Для корректного формирования адреса применим встроенную функцию КодироватьСтроку:
ПараметрПути = "Тестовые данные";
ЗакодированныйПараметр = КодироватьСтроку(ПараметрПути, СпособКодированияСтроки.КодировкаURL);
// Результат кодирования: "%D0%A2%D0%B5%D1%81%D1%82%D0%BE%D0%B2%D1%8B%D0%B5%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5"
ОтносительныйURL = "/ppmen/hs/WebExchange/888/" + ЗакодированныйПараметр;
Запрос = Новый HTTPЗапрос(ОтносительныйURL);
Обратим внимание на заголовки запроса. Конструкция вида Заголовки.Вставить("host", Сервер); является избыточной: объект HTTPСоединение формирует заголовок Host автоматически на основании переданного имени сервера и порта. Дублирование заголовка вручную может приводить к сбоям маршрутизации на некоторых веб-серверах.
Также важно помнить: если база 1С вызывает свой собственный HTTP-сервис из пользовательского сеанса в файловом режиме, может возникнуть взаимоблокировка таблиц информационной базы. Для фоновых обменов внутри одного контура предпочтительно использовать асинхронные очереди или регламентные задания.
Соберем все рекомендации воедино и посмотрим на надежный пример отправки GET-запроса к опубликованному HTTP-сервису:
Сервер = "127.0.0.1";
Порт = 80;
Пользователь = "web";
Пароль = "777";
// Настройка прокси во избежание перехвата локальных вызовов
Прокси = Новый ИнтернетПрокси;
Прокси.НеИспользоватьПроксиДляАдресов = "localhost, 127.0.0.1";
Прокси.НеИспользоватьПроксиДляЛокальныхСетей = Истина;
Соединение = Новый HTTPСоединение(
Сервер,
Порт,
Пользователь,
Пароль,
Прокси,
30 // Таймаут в секундах
);
// Кодирование кириллической части адреса
СегментПути = КодироватьСтроку("Тестовые данные", СпособКодированияСтроки.КодировкаURL);
ОтносительныйАдрес = "/ppmen/hs/WebExchange/888/" + СегментПути;
Запрос = Новый HTTPЗапрос(ОтносительныйАдрес);
Попытка
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку();
Сообщить("Успешный ответ: " + ТекстОтвета);
Иначе
Сообщить("Сервер вернул код: " + Ответ.КодСостояния, СтатусСообщения.Внимание);
КонецЕсли;
Исключение
Сообщить("Не удалось выполнить запрос: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;