Как передать текст запроса через HTTP-сервис и получить результат обратно в 1С?

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

В процессе интеграции двух баз 1С часто возникает задача удаленного выполнения запроса. Мы рассмотрим, как правильно передать текст запроса от клиента к серверу, выполнить его и вернуть результат (таблицу значений) в формате JSON или через ХранилищеЗначения. Разберем основные проблемы, такие как передача спецсимволов в URL и ограничения сериализации ссылочных типов.

Способ 1. Передача текста запроса через GET-параметры

При использовании метода GET параметры передаются непосредственно в строке адреса. Основная сложность здесь заключается в том, что текст запроса содержит пробелы, переносы строк и символы табуляции, которые могут «сломать» URL. Рассмотрим, как подготовить строку запроса перед отправкой.

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


ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 10 Номенклатура.Наименование КАК Имя ИЗ Справочник.Номенклатура";

// Очистка от спецсимволов для упрощения строки
ТекстЗапроса1 = СтрЗаменить(ТекстЗапроса, Символы.Таб, " ");
ТекстЗапроса1 = СтрЗаменить(ТекстЗапроса1, Символы.ПС, " ");
ТекстЗапроса1 = СтрЗаменить(ТекстЗапроса1, Символы.НПП, " ");

// Важно: обязательное URL-кодирование для корректной передачи спецсимволов (&, +, =)
ТекстЗапросаБезопасный = КодироватьСтроку(ТекстЗапроса1, СпособКодированияСтроки.КодировкаURL);

ЗапросHTTP = Новый HTTPЗапрос(АдресСервиса + "?QueryText=" + ТекстЗапросаБезопасный, Заголовки);

Важное замечание: помните об ограничениях веб-серверов (Apache, IIS) на длину URL (обычно около 2048 символов). Если ваш текст запроса очень большой, рекомендуем использовать метод POST и передавать текст запроса в теле сообщения.

Способ 2. Возврат результата запроса (Таблицы Значений) через JSON

После выполнения запроса на стороне сервера нам нужно передать таблицу значений обратно. Мы выяснили, что стандартный СериализаторXDTO не всегда корректно восстанавливает ТаблицаЗначений из JSON без предварительного описания типов. Рассмотрим наиболее универсальный и надежный метод — преобразование таблицы в массив структур.

Разберем по шагам процесс на стороне сервера (в HTTP-сервисе):

  1. Выполняем запрос и получаем таблицу значений.
  2. Обходим таблицу и формируем массив структур, где ключи — это имена колонок.
  3. Сериализуем массив в строку JSON.

// На стороне сервера (HTTP-сервис)
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

МассивРезультата = Новый Массив;
Для Каждого СтрокаТЗ Из РезультатЗапроса Цикл
    СтруктураСтроки = Новый Структура;
    Для Каждого Колонка Из РезультатЗапроса.Колонки Цикл
        // Обработка ссылочных типов: JSON не понимает ссылки 1С
        Значение = СтрокаТЗ[Колонка.Имя];
        Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
            СтруктураСтроки.Вставить(Колонка.Имя, Строка(Значение.УникальныйИдентификатор()));
        Иначе
            СтруктураСтроки.Вставить(Колонка.Имя, Значение);
        КонецЕсли;
    КонецЦикла;
    МассивРезультата.Добавить(СтруктураСтроки);
КонецЦикла;

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивРезультата);
СтрокаJSON = ЗаписьJSON.Закрыть();

Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(СтрокаJSON);
Возврат Ответ;

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


// На стороне клиента
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоОтвета);
Данные = ПрочитатьJSON(ЧтениеJSON); // Получаем Массив Соответствий или Структур

ТЗ_Результат = Новый ТаблицаЗначений;
Если Данные.Количество() > 0 Тогда
    // Создаем колонки по первому элементу
    Для Каждого КлючИЗначение Из Данные[0] Цикл
        ТЗ_Результат.Колонки.Добавить(КлючИЗначение.Ключ);
    КонецЦикла;
    
    // Заполняем данными
    Для Каждого ЭлементДанных Из Данные Цикл
        НоваяСтр = ТЗ_Результат.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтр, ЭлементДанных);
    КонецЦикла;
КонецЕсли;

Способ 3. Использование Хранилища Значения для передачи любых данных

Если обе базы работают на платформе 1С и вам нужно передать сложные типы данных (включая саму ТаблицаЗначений целиком со всеми типами колонок), можно использовать ХранилищеЗначения. Этот способ позволяет упаковать объект в бинарные данные, закодировать их в Base64 и передать как строку.

Рассмотрим пример реализации отправки:


// На стороне сервера (упаковка)
ХЗ = Новый ХранилищеЗначения(РезультатЗапроса, Новый СжатиеДанных(9));
СтрокаДляПередачи = XMLСтрока(ХЗ); // Преобразует бинарные данные в Base64 строку

Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(СтрокаДляПередачи);
Возврат Ответ;

И получение на стороне клиента:


// На стороне клиента (распаковка)
ТекстОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
ХЗ = XMLЗначение(Тип("ХранилищеЗначения"), ТекстОтвета);
РезультатТаблица = ХЗ.Получить(); // Здесь уже полноценная ТаблицаЗначений

Преимущество данного метода: сохраняется типизация колонок и структура таблицы без ручного перебора строк. Однако, этот метод работает только между двумя базами 1С и не подходит для интеграции с внешними системами (например, на Python или JS).

Проблема ссылочных данных

Выясним важную деталь: при передаче данных через JSON ссылки 1С превращаются в обычные строки. Если вы передадите Ссылка, в JSON попадет либо её текстовое представление, либо внутренний идентификатор. Чтобы принимающая база смогла найти этот же объект у себя, рекомендуется всегда передавать GUID (Уникальный Идентификатор) и, при необходимости, тип объекта.

В тексте запроса на сервере это можно сделать так:

ВЫБРАТЬ ПРЕДСТАВЛЕНИЕ(Договор.Ссылка) КАК ДоговорИмя, Договор.Ссылка КАК Ссылка...

А при упаковке в структуру извлекать УникальныйИдентификатор(), как было показано во втором способе.

Безопасность и оптимизация

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

Рекомендации по улучшению:

Таким образом, мы рассмотрели несколько способов обмена данными: от простых строковых параметров до передачи сериализованных объектов через ХранилищеЗначения. Выбор конкретного метода зависит от требований к универсальности (JSON) или к скорости разработки и сохранению типов (ХранилищеЗначения).

← На главную