При публикации баз 1С на веб-сервере Microsoft IIS и организации внешнего доступа через отдельный порт разработчики часто сталкиваются с ситуацией, когда схема WSDL успешно открывается в браузере по внешнему адресу, однако при попытке вызвать веб-сервис из кода 1С возникает ошибка: «При вызове веб-сервиса произошла ошибка. Неизвестная ошибка. Ошибка работы с Интернет: Не могу установить соединение». Проанализируем причину такого поведения и рассмотрим по шагам методы решения проблемы.
Выясним причину ошибки, разобрав поэтапно процесс взаимодействия клиента 1С с SOAP веб-сервисом:
http://test.ru:832/test1Cdb/ws/testnamepub.1cws?wsdl). Этот запрос проходит через роутер и веб-сервер, возвращая XML-документ с описанием сервиса.location тега <soap:address>, который содержится внутри полученного WSDL-файла.wsisapi.dll) генерирует адрес в location динамически, основываясь на заголовках и параметрах запроса, переданных от IIS. Если на сетевом шлюзе внешний порт 832 перенаправляется на стандартный локальный порт 80, IIS сообщает модулю 1С, что запрос поступил на порт 80. В результате в блоке <soap:address location="..."> формируется адрес без указания порта 832.location (на стандартный порт 80), который из внешней сети недоступен или закрыт брандмауэром. В этот момент и возникает ошибка подключения.Распространенным заблуждением является попытка прописать порт в URI пространства имен сервиса (targetNamespace). Пространство имен служит исключительно уникальным строковым идентификатором типов данных в XML-схеме, реальных сетевых запросов по нему платформа не делает, поэтому изменение URI проблему не решает.
Самым правильным и прозрачным решением является обеспечение сквозного использования одного и того же порта на всех участках сети:
8080 или 832) для всех IP-адресов.832 должен транслироваться на локальный порт 832 сервера с IIS, а не на 80-й.
iisreset
После этого IIS будет передавать модулю 1С фактический номер порта, и генерируемый WSDL будет содержать правильный атрибут <soap:address location="http://test.ru:832/test1Cdb/ws/testnamepub.1cws"/>.
Если изменить сетевые настройки маршрутизатора или IIS невозможно, разберем обходной путь на стороне вызывающей конфигурации 1С. Поскольку свойство Местоположение у объектов коллекции Сервисы в WSОпределения доступно только для чтения, переопределить адрес в памяти нельзя. Однако можно инициализировать определение из предварительно скорректированного файла.
Разберем по шагам реализацию данного механизма:
location, добавив необходимый внешний порт.WSОпределения.Посмотрим на пример кода на стороне клиента 1С:
// Получаем WSDL-схему через HTTP-запрос
HTTPЗапрос = Новый HTTPЗапрос("/test1Cdb/ws/testnamepub.1cws?wsdl");
HTTPСоединение = Новый HTTPСоединение("test.ru", 832, "Пользователь", "Пароль");
HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
Если HTTPОтвет.КодСостояния = 200 Тогда
ТекстWSDL = HTTPОтвет.ПолучитьТелоКакСтроку();
// Подменяем адрес точки подключения, подставляя внешний порт
СтарыйАдрес = "http://test.ru/test1Cdb/ws/testnamepub.1cws";
НовыйАдрес = "http://test.ru:832/test1Cdb/ws/testnamepub.1cws";
ТекстWSDL = СтрЗаменить(ТекстWSDL, СтарыйАдрес, НовыйАдрес);
// Сохраняем во временный файл
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("wsdl");
ЗаписьТекста = Новый ЗаписьТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);
ЗаписьТекста.Записать(ТекстWSDL);
ЗаписьТекста.Закрыть();
// Создаем WSОпределения из локального файла
Определения = Новый WSОпределения(ИмяВременногоФайла, "Пользователь", "Пароль");
Прокси = Новый WSПрокси(Определения, "http://test.ru/ws/testname", "testnamepub", "testnamepubSoap");
Прокси.Пользователь = "Пользователь";
Прокси.Пароль = "Пароль";
// Вызов метода веб-сервиса
Результат = Прокси.ТестовыйМетод();
УдалитьФайлы(ИмяВременногоФайла);
КонецЕсли;
Еще один вариант централизованного исправления — использование официального модуля URL Rewrite для IIS. В конфигурационном файле web.config опубликованной базы можно настроить правило исходящей перезаписи (Outbound Rule), которое перехватывает все ответы с WSDL и автоматически заменяет строку адреса на необходимую, добавляя нужный порт перед отправкой клиенту.