Создать WSОпределения только из проверенного собственного локального файла

Учебные задачи

Сравним локальное описание с импортированной WS-ссылкой после строгой проверки полного текста файла, не загружая WSDL по внешнему URL.

Где и как запускать

Полный обычный клиентский общий модуль УчебныеКонтракты85, только толстый клиент. Пульт и локальный WSDL отдельными полными блоками ниже.

Подготовка

  1. НОВАЯ собственная файловая база 8.5.1.1343 с именем конфигурации УчебныеКонтрактыМетаданных85, совместимость НеИспользовать, обычное приложение и толстый клиент. Можно использовать уже подготовленный собственный стенд уроков контрактов метаданных. Не рабочая база и не её копия; нет расширений, разделителей и других сеансов. Здесь runtimeVerifiedScenarios=0.

  2. Общий модуль УчебныеКонтракты85: неглобальный, Клиент (обычное приложение)=Да, Сервер=Нет, остальные клиентские флаги=Нет, Привилегированный=Нет. Вставьте полный модуль одного выбранного урока. Обработка УчебныеКонтракты85 → обычная основная форма Пульт → кнопка Выполнить → действие ВыполнитьНажатие; полный модуль формы приведён отдельно.

  3. Для всех трёх уроков: сохраните полный XML/WSDL из отдельного блока ниже в UTF-8. Создайте только свою WS-ссылку УчебныйСервис85 и импортируйте WSDL ИЗ ЛОКАЛЬНОГО ФАЙЛА, не по HTTP. StudyService85, namespace urn:guide:metadata85, StudyPort85 и Echo заданы в этом полном описании. Во втором уроке сравниваются файл и этот собственный импорт. Не нужны внешний источник, палитра или рабочие бизнес-данные.

  4. WSDL содержит встроенную XSD без import/include, один сервис и порт, операцию Echo с входным сообщением и ответом. Адрес http://127.0.0.1:9/metadata-study-85 — учебная строка описания; этот урок не публикует по ней сервис и не проверяет, свободен ли порт. Никакая операция SOAP не вызывается.

  5. Для второго урока человек сохраняет тот же XML строго как C:\1CStudy85\metadata-study-85.wsdl, UTF-8 без BOM. Допускаются LF/CRLF и завершающий перевод строки; иной текст код отклоняет ДО конструктора WSОпределения. Каталог и файл создайте сами только для своего опыта. Здесь файл на этом пути не создавался.

  6. Свой файл не должен меняться между проверкой текста и конструктором; нет другого процесса, который его заменяет. Это одиночный учебный стенд, не защита от гонки или недоверенного WSDL. Не подставляйте внешние URL и не добавляйте импорты.

  7. F7 и обновление только собственной базы. Первый урок выводит паспорт описания. Второй сравнивает своё локальное описание с импортированным. Третий создаёт два локальных объекта WSПрокси и проверяет настройки, НЕ вызывает Echo и не создаёт настоящую интеграцию.

  8. Табличные документы создаются только в памяти и показываются readonly без имени файла. Не печатайте/не сохраняйте из окна. В третьем уроке логин и пароль — заведомо ненастоящие локальные строки; пароль не выводится. Рабочие учётные данные запрещены.

Процедура ВыполнитьПример() Экспорт
    ПроверитьСвойКонтекст();
    ИмяФайла = "C:\1CStudy85\metadata-study-85.wsdl";
    ФайлОписания = Новый Файл(ИмяФайла);
    Если Не ФайлОписания.Существует() Тогда
        ВызватьИсключение "Человек должен заранее сохранить только свой приложенный локальный WSDL";
    КонецЕсли;
    ДокументТекста = Новый ТекстовыйДокумент;
    ДокументТекста.Прочитать(ИмяФайла, "UTF-8", "");
    ОжидаемыйТекст = "<?xml version=""1.0"" encoding=""UTF-8""?>
|<definitions xmlns=""http://schemas.xmlsoap.org/wsdl/"" xmlns:tns=""urn:guide:metadata85"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/wsdl/soap/"" targetNamespace=""urn:guide:metadata85"" name=""MetadataStudy85"">
|  <types>
|    <xsd:schema targetNamespace=""urn:guide:metadata85"" elementFormDefault=""qualified"">
|      <xsd:element name=""Echo""><xsd:complexType><xsd:sequence><xsd:element name=""text"" type=""xsd:string""/></xsd:sequence></xsd:complexType></xsd:element>
|      <xsd:element name=""EchoResponse""><xsd:complexType><xsd:sequence><xsd:element name=""text"" type=""xsd:string""/></xsd:sequence></xsd:complexType></xsd:element>
|    </xsd:schema>
|  </types>
|  <message name=""EchoRequest""><part name=""parameters"" element=""tns:Echo""/></message>
|  <message name=""EchoResponse""><part name=""parameters"" element=""tns:EchoResponse""/></message>
|  <portType name=""StudyPortType""><operation name=""Echo""><input message=""tns:EchoRequest""/><output message=""tns:EchoResponse""/></operation></portType>
|  <binding name=""StudyBinding"" type=""tns:StudyPortType"">
|    <soap:binding style=""document"" transport=""http://schemas.xmlsoap.org/soap/http""/>
|    <operation name=""Echo""><soap:operation soapAction=""urn:guide:metadata85:Echo""/><input><soap:body use=""literal""/></input><output><soap:body use=""literal""/></output></operation>
|  </binding>
|  <service name=""StudyService85""><port name=""StudyPort85"" binding=""tns:StudyBinding""><soap:address location=""http://127.0.0.1:9/metadata-study-85""/></port></service>
|</definitions>
|";
    Прочитанный = НормализоватьПереводыСтрок(ДокументТекста.ПолучитьТекст());
    Если Прочитанный <> НормализоватьПереводыСтрок(ОжидаемыйТекст) Тогда
        ВызватьИсключение "Иной WSDL, импорт или внешний URL не допускаются до конструктора";
    КонецЕсли;
    ИзФайла = Новый WSОпределения(ИмяФайла);
    ИзМетаданных = ПолучитьСвоиОпределения();
    Если ТипЗнч(ИзФайла) <> Тип("WSОпределения") Или ИзФайла.Сервисы.Количество() <> 1 Тогда
        ВызватьИсключение "Собственный локальный файл должен дать одно определение сервиса";
    КонецЕсли;
    Локальный = ИзФайла.Сервисы.Получить("urn:guide:metadata85", "StudyService85");
    Импортированный = ИзМетаданных.Сервисы.Получить("urn:guide:metadata85", "StudyService85");
    Если Локальный.Имя <> Импортированный.Имя Или Локальный.URIПространстваИмен <> Импортированный.URIПространстваИмен
        Или Локальный.ТочкиПодключения.Получить("StudyPort85").Местоположение
            <> Импортированный.ТочкиПодключения.Получить("StudyPort85").Местоположение Тогда
        ВызватьИсключение "Собственный локальный и импортированный контракты не согласованы";
    КонецЕсли;
    Сообщить("Локальный WSОпределения совпал с импортом по сервису, namespace и адресу порта. SOAP не вызывался.");
КонецПроцедуры

Функция НормализоватьПереводыСтрок(Текст)
    Текст = СтрЗаменить(Текст, Символы.ВК + Символы.ПС, Символы.ПС);
    Текст = СтрЗаменить(Текст, Символы.ВК, Символы.ПС);
    Возврат СокрЛП(Текст);
КонецФункции

Процедура ПроверитьСвойКонтекст()
    Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Тогда
        ВызватьИсключение "Нужен собственный стенд УчебныеКонтрактыМетаданных85 платформы 8.5.1.1343";
    КонецЕсли;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Учебный вывод не должен выполняться внутри чужой транзакции";
    КонецЕсли;
КонецПроцедуры

Функция ПолучитьСвоиОпределения()
    ПроверитьСвойКонтекст();
    Если Метаданные.WSСсылки.Найти("УчебныйСервис85") = Неопределено Тогда
        ВызватьИсключение "Импортируйте свой приложенный локальный WSDL в УчебныйСервис85";
    КонецЕсли;
    МенеджерыСсылок = WSСсылки;
    МенеджерСсылки = МенеджерыСсылок.УчебныйСервис85;
    Определения = МенеджерСсылки.ПолучитьWSОпределения();
    Если ТипЗнч(Определения) <> Тип("WSОпределения") Или Определения.Сервисы.Количество() <> 1 Тогда
        ВызватьИсключение "Нужно собственное описание с одним сервисом";
    КонецЕсли;
    Сервис = Определения.Сервисы.Получить("urn:guide:metadata85", "StudyService85");
    Если Сервис.Имя <> "StudyService85" Или Сервис.URIПространстваИмен <> "urn:guide:metadata85"
        Или Сервис.ТочкиПодключения.Количество() <> 1 Тогда
        ВызватьИсключение "Не совпал сервис своего локального WSDL";
    КонецЕсли;
    Точка = Сервис.ТочкиПодключения.Получить("StudyPort85");
    Если Точка.Имя <> "StudyPort85" Или Точка.Местоположение <> "http://127.0.0.1:9/metadata-study-85" Тогда
        ВызватьИсключение "Не совпали порт и учебный адрес; никаких вызовов не выполняем";
    КонецЕсли;
    Возврат Определения;
КонецФункции
УчебныеКонтракты85.Пульт

УчебныеКонтрактыМетаданных85 → Обработки → УчебныеКонтракты85 → Формы → Пульт → Модуль

Полный модуль своей обычной формы, не выполнялся.

Процедура ВыполнитьНажатие(Кнопка)
    УчебныеКонтракты85.ВыполнитьПример();
КонецПроцедуры
metadata-study-85.wsdl

Полный локальный UTF-8 XML/WSDL для своего импорта; для файлового урока C:\1CStudy85\metadata-study-85.wsdl.

Это XML, не BSL и не работающий сервис. Импорты и include отсутствуют.

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="urn:guide:metadata85" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="urn:guide:metadata85" name="MetadataStudy85">
  <types>
    <xsd:schema targetNamespace="urn:guide:metadata85" elementFormDefault="qualified">
      <xsd:element name="Echo"><xsd:complexType><xsd:sequence><xsd:element name="text" type="xsd:string"/></xsd:sequence></xsd:complexType></xsd:element>
      <xsd:element name="EchoResponse"><xsd:complexType><xsd:sequence><xsd:element name="text" type="xsd:string"/></xsd:sequence></xsd:complexType></xsd:element>
    </xsd:schema>
  </types>
  <message name="EchoRequest"><part name="parameters" element="tns:Echo"/></message>
  <message name="EchoResponse"><part name="parameters" element="tns:EchoResponse"/></message>
  <portType name="StudyPortType"><operation name="Echo"><input message="tns:EchoRequest"/><output message="tns:EchoResponse"/></operation></portType>
  <binding name="StudyBinding" type="tns:StudyPortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="Echo"><soap:operation soapAction="urn:guide:metadata85:Echo"/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation>
  </binding>
  <service name="StudyService85"><port name="StudyPort85" binding="tns:StudyBinding"><soap:address location="http://127.0.0.1:9/metadata-study-85"/></port></service>
</definitions>

Разбор по шагам

  1. ИмяФайла — фиксированный собственный локальный путь, не входной URL пользователя. Проверяем Существует; отсутствие файла даёт понятный отказ, файл автоматически не создаётся.

  2. ТекстовыйДокумент.Прочитать получает UTF-8 и пустой разделитель: перевод строк сначала сохраняется как есть. Затем нормализуем CRLF/CR в LF и убираем только внешние пробелы для текстового сравнения.

  3. Полный ожидаемый WSDL встроен прямо в основной модуль, а отдельный XML-блок нужен человеку для подготовки. Любое другое содержимое, в том числе новый import/include, отклоняется ДО WS-конструктора.

  4. Новый WSОпределения получает обязательный МестоположениеWSDL в виде собственного локального имени файла. Учётные данные, HTTP-прокси, TLS и сетевой таймаут не задаются для локального чтения.

  5. ПолучитьСвоиОпределения берёт описание собственной WS-ссылки. Это другой источник, поэтому сравниваем выбранные семантические признаки, а не тождество двух объектов в памяти.

  6. Сравниваем StudyService85, namespace и адрес StudyPort85. Это проверка выбранных признаков двух описаний, не полное доказательство эквивалентности любых WSDL.

  7. Конструктор некорректного WSDL может вызвать исключение. Здесь некорректный или изменённый файл отсеивается раньше; код не подавляет ошибку и не объявляет пустое описание успехом.

Как проверить результат

  1. Будущий тест: сохранён точный свой XML, импортирован тот же файл, F7 и Пульт. Ожидается сообщение согласованности сервиса, namespace и адреса порта; runtimeVerifiedScenarios=0.

  2. LF и CRLF должны проходить нормализацию; UTF-8 без BOM входит в подготовку. Текстовая проверка намеренно строгая, это не универсальная каноникализация XML.

  3. Измените своё имя сервиса или добавьте import в локальный файл без переимпорта: текстовый guard должен отказать ДО Новый WSОпределения.

  4. При отсутствии своего файла выводится отказ, нет записи нового файла, сетевого fallback или загрузки из URLИсточника.

  5. Точный экземпляр файла не должен заменяться другим процессом между проверкой и чтением конструктора. Этот стенд не защищает от гонки и не обрабатывает недоверенные загрузки.

Ожидаемый результат

Подготовлен собственный локальный опыт без вызова операций веб-сервиса. Код и UI здесь не выполнялись: runtimeVerifiedScenarios=0.

На что обратить внимание

  1. Описание WSDL и объект вызова WSПрокси — не результат работы внешней системы. Здесь Echo не вызывается и работоспособность сервиса не проверяется.

  2. Имена сервисов выбираются парой namespace/локальное имя; URI namespace не является URL для сетевого запроса. Местоположение порта — адрес будущего вызова, а URLИсточника WS-ссылки — источник WSDL.

  3. Все описания WS, коллекции и транспортные свойства, кроме логина/пароля WSПрокси, здесь только читаются. Коллекции описания не имеют выдуманных конструкторов, Добавить или Удалить.

  4. Тип WS-параметра/ответа — описание XDTO, а не готовое передаваемое значение и не ОписаниеТипов 1С. ВозможноПустой/ВозможноПустое описывают допустимость Неопределено, не обязательное наличие такого значения.

  5. Статическая проверка не является импортом WSDL, F7, реальным SOAP-тестом или подтверждением точного отображения document/literal параметров платформой.

  6. Текстовая проверка не удерживает файловую блокировку до конструктора. Нельзя переносить её в production как защиту от подмены WSDL или SSRF.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.