Как исправить ошибку «Каталог не обнаружен '?wsdl'» (sfile://?wsdl) в 1С:Предприятие

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием IT и автоматизация бизнеса
← На главную

При интеграции систем на платформе 1С:Предприятие с внешними информационными базами через веб-сервисы разработчики часто сталкиваются с неочевидным поведением платформы. Одной из таких проблем является ошибка вызова конструктора WSОпределения, сопровождающаяся загадочным сообщением: «При создании описания сервиса произошла ошибка. URL сервиса: sfile://?wsdl по причине: Каталог не обнаружен '?wsdl'».

В этой статье мы подробно разберем природу возникновения данной ошибки, проанализируем внутренние механизмы платформы 1С, приводящие к её появлению, и выработаем надежные методы защиты кода, которые навсегда исключат возникновение подобных ситуаций в ваших конфигурациях.

Почему возникает протокол sfile:// и ошибка «Каталог не обнаружен»?

Для того чтобы понять суть проблемы, нам необходимо заглянуть во внутреннюю логику работы платформы 1С при создании описания веб-сервиса. Рассмотрим стандартный конструктор создания веб-сервиса:


Определения = Новый WSОпределения(ПараметрыПодключения.URLReports + "?wsdl", ПараметрыПодключения.Пользователь, ПараметрыПодключения.Пароль);

В штатном режиме переменная ПараметрыПодключения.URLReports содержит валидный URL-адрес публикации веб-сервиса (например, http://server/erp/ws/reports). Платформа конкатенирует его со строкой "?wsdl", получает адрес http://server/erp/ws/reports?wsdl, успешно обращается по протоколу HTTP/HTTPS и загружает схему.

Однако, если переменная URLReports по какой-то причине оказывается пустой строкой, итоговый путь, передаваемый в конструктор, превращается в строку "?wsdl". Проанализируем, как на это реагирует 1С:

  1. Платформа анализирует переданную строку на наличие стандартных сетевых протоколов (http://, https://, ftp://).
  2. Не обнаружив признаков сетевого адреса, 1С предполагает, что ей передан локальный или сетевой путь к файлу схемы на диске (например, в формате file:// или в виде относительного пути).
  3. Для обеспечения безопасности и изоляции сеансов сервер 1С транслирует неопределенные относительные пути во внутренний безопасный протокол доступа к файлам сервера — sfile:// (Server File).
  4. В результате относительный путь "?wsdl" преобразуется сервером в системный адрес sfile://?wsdl.
  5. Платформа пытается найти на сервере физический каталог или файл с именем ?wsdl. Поскольку символы вопросов и другие спецсимволы некорректны для имен папок, а сам каталог физически отсутствует, операционная система возвращает ошибку: «Каталог не обнаружен '?wsdl'».

Таким образом, появление в ошибке протокола sfile:// — это прямой маркер того, что в платформу был передан пустой или некорректный базовый URL-адрес.

Глубинные причины пустого URL: разбираем код

Выяснив, что корень проблемы кроется в пустом адресе, проанализируем типичный код получения параметров подключения, который часто становится источником этой ошибки:


Функция ПолучитьПараметрыПодключенияERP(МакетКомпоновки)
    Результат = Новый Структура("Пользователь, Пароль, URLReports", "", "", "");
    УстановитьПривилегированныйРежим(Истина);
    Попытка
        УзелERP = БИТ_СТ_ПовторноеИспользованиеЗначений.ПолучитьЗначениеКонстанты("СТ_НСИ_УзелERP");
        Если ЗначениеЗаполнено(УзелERP) Тогда
            РеквизитыУзла = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(УзелERP, "URL,Пользователь,Пароль,ИнформационнаяБазаИсточник");
            Результат.Пользователь = РеквизитыУзла.Пользователь;
            Результат.Пароль = РеквизитыУзла.Пароль;
            Результат.URLReports = РеквизитыУзла.URL;
        КонецЕсли;
    Исключение
        // Пустой блок!
    КонецПопытки;
    УстановитьПривилегированныйРежим(Ложь);
    Возврат Результат;
КонецФункции

При детальном рассмотрении этой функции мы можем обнаружить три серьезные архитектурные ловушки, которые гарантируют появление пустых значений параметров.

Ловушка №1: Кэширование значений (Повторное использование)

В строке получения константы используется вызов специализированного модуля: БИТ_СТ_ПовторноеИспользованиеЗначений.ПолучитьЗначениеКонстанты("СТ_НСИ_УзелERP"). Этот общий модуль имеет свойство «Повторное использование возвращаемых значений» (на время вызова или на время сеанса).

Рассмотрим ситуацию по шагам:

  1. При запуске системы или первом обращении к интеграции константа СТ_НСИ_УзелERP была пустой (например, база только разворачивается или настройки еще не заданы).
  2. Платформа вызвала функцию получения константы, вернула пустое значение и закэшировала его на уровне сеанса.
  3. Администратор заходит в систему, обнаруживает отсутствие настроек, заполняет константу, указывает узел ERP и прописывает корректный URL-адрес.
  4. Администратор запускает интеграцию повторно без перезапуска сеанса 1С. Метод ПолучитьЗначениеКонстанты обращается к кэшу и снова мгновенно возвращает старое пустое значение, игнорируя новые данные в базе данных!
  5. В результате система падает с ошибкой sfile://?wsdl, вызывая недоумение у администратора, который своими глазами видит заполненные поля в интерфейсе.

Решение проблемы кэша: Для применения настроек «на лету» без перезапуска клиентских сеансов необходимо программно сбрасывать кэш повторно используемых модулей. Сделать это можно с помощью встроенного метода платформы:

ОбновитьПовторноИспользуемыеЗначения();

Этот метод очистит кэш текущего сеанса, вынудив платформу при следующем вызове прочитать актуальные настройки непосредственно из базы данных.

Ловушка №2: Пустой блок Попытка...Исключение

Использование пустых блоков Исключение (так называемое «замалчивание» ошибок) — это один из самых опасных антипаттернов в разработке на 1С. В приведенном коде любая критическая ошибка внутри блока Попытка останется незамеченной:

Из-за пустого блока Исключение программа тихо проглотит эту ошибку. Переменная Результат.URLReports останется пустой строкой, управление передастся дальше, и разработчик получит неинформативное сообщение о каталоге ?wsdl вместо реальной ошибки обращения к метаданным.

Решение проблемы скрытых ошибок: Блок исключения всегда должен фиксировать произошедший сбой в системном Журнале регистрации:


Попытка
    // Получение параметров...
Исключение
    ЗаписьЖурналаРегистрации("Интеграция.ПодключениеERP",
        УровеньЖурналаРегистрации.Ошибка,
        ,
        ,
        ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

Ловушка №3: Ссылка есть, а данных нет

Метод ЗначениеЗаполнено(УзелERP) проверяет лишь то, что в константе выбрана ссылка на объект (например, на конкретный узел плана обмена или элемент справочника). Однако сама по себе заполненная ссылка не гарантирует, что внутри этого объекта заполнены строковые реквизиты адреса и авторизации.

Если узел создан, но поле URL внутри него оставлено пустым, проверка на заполненность узла вернет Истина, а на выходе мы снова получим пустой адрес.

Разрабатываем отказоустойчивый код подключения

Для того чтобы полностью обезопасить систему от подобных ошибок, спроектируем надежный и понятный алгоритм проверки параметров перед вызовом конструктора WSОпределения. Разберем его реализацию по шагам.

Напишем безопасную функцию получения параметров с обязательным логированием сбоев:


Функция ПолучитьНадежныеПараметрыПодключения() Экспорт
    
    Параметры = Новый Структура;
    Параметры.Вставить("Успешно", Ложь);
    Параметры.Вставить("Пользователь", "");
    Параметры.Вставить("Пароль", "");
    Параметры.Вставить("URLReports", "");
    Параметры.Вставить("ТекстОшибки", "");
    
    УстановитьПривилегированныйРежим(Истина);
    
    Попытка
        УзелERP = БИТ_СТ_ПовторноеИспользованиеЗначений.ПолучитьЗначениеКонстанты("СТ_НСИ_УзелERP");
        
        Если Не ЗначениеЗаполнено(УзелERP) Тогда
            Параметры.ТекстОшибки = "В настройках системы не заполнена константа 'СТ_НСИ_УзелERP'!";
            Возврат Параметры;
        КонецЕсли;
        
        // Читаем реквизиты безопасным методом
        РеквизитыУзла = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(УзелERP, "URL, Пользователь, Пароль");
        
        Если ПустаяСтрока(РеквизитыУзла.URL) Тогда
            Параметры.ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
                "В узле подключения '%1' не заполнен реквизит 'URL'!", СокрЛП(УзелERP));
            Возврат Параметры;
        КонецЕсли;
        
        Параметры.Пользователь = РеквизитыУзла.Пользователь;
        Параметры.Пароль       = РеквизитыУзла.Пароль;
        Параметры.URLReports   = СокрЛП(РеквизитыУзла.URL);
        Параметры.Успешно      = Истина;
        
    Исключение
        Параметры.ТекстОшибки = "Системная ошибка при чтении настроек подключения: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
        ЗаписьЖурналаРегистрации("Интеграция.ПараметрыПодключения",
            УровеньЖурналаРегистрации.Ошибка,
            ,,
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    
    УстановитьПривилегированныйРежим(Ложь);
    
    Возврат Параметры;
    
КонецФункции

Теперь реализуем безопасный вызов веб-сервиса с валидацией полученных настроек перед обращением к конструктору:


Процедура ИнициализироватьВебСервис()
    
    ПараметрыПодключения = ПолучитьНадежныеПараметрыПодключения();
    
    Если Не ПараметрыПодключения.Успешно Тогда
        // Сообщаем пользователю понятным языком, что именно пошло не так
        ВызватьИсключение "Не удалось подключиться к ERP: " + ПараметрыПодключения.ТекстОшибки;
    КонецЕсли;
    
    // Формируем результирующий URL
    АдресWSDL = ПараметрыПодключения.URLReports;
    Если Не СтрЗаканчиваетсяНа(АдресWSDL, "?wsdl") И Не СтрЗаканчиваетсяНа(АдресWSDL, "?WSDL") Тогда
        АдресWSDL = АдресWSDL + "?wsdl";
    КонецЕсли;
    
    Попытка
        // Безопасный вызов конструктора с гарантированно заполненным URL
        Определения = Новый WSОпределения(АдресWSDL, ПараметрыПодключения.Пользователь, ПараметрыПодключения.Пароль);
        
        // Дальнейшая работа с веб-сервисом...
        
    Исключение
        ВызватьИсключение "Ошибка инициализации WS-соединения: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
    КонецПопытки;
    
КонецПроцедуры

Резюме и чеклист для быстрой проверки

Если вы столкнулись с ошибкой каталога ?wsdl на сервере 1С, выполните следующие действия по шагам:

  1. Проверьте значение переменной URL: Выведите её в отладчике непосредственно перед вызовом конструктора WSОпределения. Скорее всего, она будет пустой.
  2. Сбросьте кэш повторного использования: Если настройки были заполнены только что, вызовите в табло отладчика метод ОбновитьПовторноИспользуемыеЗначения() или перезапустите сеанс.
  3. Оцените целостность метаданных: Убедитесь, что реквизит, хранящий URL-адрес в базе данных, действительно существует, заполнен в конкретном элементе справочника и к нему есть права доступа у текущего сеанса.
  4. Уберите пустые перехватчики ошибок: Замените все конструкции Попытка...Исключение //КонецПопытки на полноценную запись ошибок в Журнал регистрации, чтобы вовремя локализовать неисправность.
← На главную