При разработке решений под веб-клиент 1С разработчики часто сталкиваются с ситуацией, когда необходимо отправить запрос к локальному сервису на компьютере пользователя (например, к службе локального торгового оборудования, криптопровайдеру или сканеру штрихкодов, слушающему адрес localhost или 127.0.0.1). Однако при попытке создать объект HTTPСоединение на веб-клиенте платформа выдает ошибку о недоступности конструктора.
Разберем подробно причины таких ограничений платформы и рассмотрим практические способы решения этой задачи.
Выясним причину архитектурного разделения объектов HTTPЗапрос и HTTPСоединение:
HTTPЗапрос: этот объект представляет собой универсальную структуру данных. Он содержит адрес ресурса, заголовки и тело запроса. Объект доступен на клиенте для того, чтобы разработчик мог сконструировать параметры запроса в клиентском контексте и передать их на сервер без лишних преобразований.HTTPСоединение: веб-клиент платформы 1С работает внутри браузерной песочницы. Движок браузера изолирует JavaScript-окружение и не предоставляет прямого низкоуровневого доступа к сетевым сокетам операционной системы. По этой причине объект HTTPСоединение доступен только на сервере, в тонком клиенте и в толстом клиенте под управлением ОС.Если выполнить запрос на сервере 1С, то обращение к localhost пойдет к локальному хосту сервера приложений, а не к компьютеру конечного пользователя. Поэтому для обращения к клиенту необходимы обходные варианты.
Проанализируем наиболее надежный и масштабируемый способ интеграции с локальными сервисами — применение Native API внешних компонент. Внешняя компонента исполняется на уровне операционной системы клиента и не подчиняется политикам браузерной песочницы.
Разберем по шагам порядок подключения и вызова компоненты в управляемой форме веб-клиента:
Посмотрим на пример асинхронного подключения внешней компоненты на клиенте:
&НаКлиенте
Асинх Процедура ПодключитьКомпонентуИОтправитьЗапрос()
Местоположение = "ОбщийМакет.КомпонентаHTTPКлиент";
ИмяКомпоненты = "HTTPRequester";
Установлена = Ждать УстановитьВнешнююКомпонентуАсинх(Местоположение);
Если Не Установлена Тогда
Сообщить("Не удалось установить внешнюю компоненту");
Возврат;
КонецЕсли;
Подключена = Ждать ПодключитьВнешнююКомпонентуАсинх(Местоположение, ИмяКомпоненты, ТипВнешнейКомпоненты.Native);
Если Подключена Тогда
Компонента = Новый ("AddIn." + ИмяКомпоненты + ".HTTPRequester");
// Выполняем обращение к методам компоненты
Результат = Компонента.SendRequest("http://127.0.0.1:8080/api/status");
Сообщить("Ответ сервиса: " + Результат);
КонецЕсли;
КонецПроцедуры
Если установка внешней компоненты нежелательна, рассмотрим вариант со встроенным полем HTML-документа. В управляемой форме размещается реквизит с типом Строка и вид элемента формы ПолеHTMLДокумента. Внутрь загружается скрипт, выполняющий сетевой запрос средствами браузера через fetch или XMLHttpRequest.
При использовании данного способа важно учитывать ключевые ограничения браузеров:
localhost считается междоменным. Локальный сервис обязан возвращать заголовок Access-Control-Allow-Origin: * (или указать точный домен базы 1С) и корректно отвечать на предварительные запросы метода OPTIONS.HTTPS, браузер заблокирует любые попытки отправить небезопасный запрос на http://localhost. В этом случае локальный сервис также должен принимать подключения по HTTPS или база должна быть открыта по HTTP.Access-Control-Allow-Private-Network: true при обращении из внешней сети.Посмотрим на пример формирования HTML-кода со скриптом и передачи результата обратно в 1С:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Формируем HTML с функцией отправки запроса
HTMLТекст =
"<html>
|<head>
|<script>
|async function sendLocalRequest() {
| try {
| let response = await fetch('http://127.0.0.1:8080/api/data', {
| method: 'GET'
| });
| let data = await response.text();
| window.location.hash = 'result:' + encodeURIComponent(data);
| } catch (error) {
| window.location.hash = 'error:' + encodeURIComponent(error.message);
| }
|}
|</script>
|</head>
|<body onload='sendLocalRequest()'>
|</body>
|</html>";
Элементы.ПолеHTML.Документ = HTMLТекст;
КонецПроцедуры
В модуле формы перехватываем изменение ссылки документа через событие ПриНажатии или обработчик изменения URL поля HTML-документа, считывая возвращенный результат.
Рассмотрим еще один вариант взаимодействия — использование протокола WebSocket. Если локальная служба поддерживает подключение по сокетам (например, ws://127.0.0.1 или wss://127.0.0.1), веб-браузер может установить двустороннее соединение с минимальными ограничениями междоменных политик.
Код инициализации сокета также встраивается через поле HTML-документа с помощью объекта JavaScript new WebSocket('ws://127.0.0.1:8080').
HTTPЗапрос и HTTPСоединение исключительно на стороне сервера.localhost пользователя наиболее стабильным решением является внешняя компонента (Native API), которая полностью снимает ограничения браузерных политик CORS и Mixed Content.