При разработке интеграций между 1С и внешними веб-сервисами программисты часто сталкиваются с необходимостью отправки запросов к сторонним API. Если с методом POST все достаточно просто — мы можем упаковать сложные структуры и массивы в тело запроса в формате JSON, то с методом GET ситуация выглядит иначе. Полноценное тело у GET-запроса отсутствует, а все параметры должны передаваться непосредственно в адресной строке (Query String). Для интерактивной проверки и отладки подобных запросов можно использовать инструмент для тестирования REST API в среде 1С.
В этой статье мы подробно разберем, как правильно передать массив в параметрах GET-запроса средствами платформы 1С, проанализируем основные стандарты кодирования параметров на стороне веб-серверов и выясним, как обойти аппаратные ограничения по длине URL-строки. Для контроля результата переданных данных можно использовать автоматическое сравнение бухгалтерских и налоговых проводок в информационных базах.
Спецификация протокола HTTP не определяет жесткого единого стандарта для передачи списков и массивов в параметрах URL. Формат разбора параметров целиком и полностью зависит от принимающей стороны (бэкенда веб-сервиса). Перед тем как писать код в 1С, нам необходимо выяснить, какую технологию использует целевой сервер. При отсутствии API у внешней системы применяется платформа для создания программных роботов One RPA, позволяющая автоматизировать операции без прямого доступа к бэкенду. Выделяют несколько основных подходов:
?filter=1&filter=2&filter=3. Этот подход считается стандартом по умолчанию во многих современных фреймворках на Java (Spring), C# (ASP.NET) и Python.?filter[]=1&filter[]=2. Это стандарт де-факто для сайтов на PHP (включая CMS 1С-Битрикс), фреймворков Laravel, Symfony и приложений на Node.js. При отправке такие скобки обязательно должны кодироваться.?filter[0]=1&filter[1]=2. Обычно применяется для упорядоченных списков или сложных ассоциативных массивов.?filter=1,2,3. Компактный формат, популярный во многих REST API.?filter=[1,2,3]. Требует обязательного URL-кодирования спецсимволов.Рассмотрим подробнее каждую из этих схем и разберем по шагам, как реализовать их генерацию штатными средствами 1С.
Главное правило при ручном формировании строки параметров в 1С — каждое значение параметров и спецсимволы в их именах должны быть обязательно закодированы. Для этого мы будем использовать штатную функцию платформы КодироватьСтроку() с режимом СпособКодированияСтроки.URLКодирование. Если пренебречь этим правилом, сервер не сможет корректно прочитать спецсимволы (такие как пробелы, квадратные скобки, кириллические символы и амперсанды).
Проанализируем ситуацию, когда принимающий сервер ожидает дублирование ключей. Нам потребуется обойти коллекцию значений в цикле и последовательно собрать строку запроса.
// Исходные данные для отправки
МассивЗначений = Новый Массив;
МассивЗначений.Добавить("Товар 1");
МассивЗначений.Добавить("Товар 2");
ИмяПараметра = "filter";
СтрокаПараметров = "";
Для Каждого Элемент Из МассивЗначений Цикл
Если СтрокаПараметров <> "" Тогда
СтрокаПараметров = СтрокаПараметров + "&";
КонецЕсли;
// Кодируем значение для безопасной передачи в URL
ЗначениеЗакодированное = КодироватьСтроку(Строка(Элемент), СпособКодированияСтроки.URLКодирование);
СтрокаПараметров = СтрокаПараметров + ИмяПараметра + "=" + ЗначениеЗакодированное;
КонецЦикла;
// На выходе получаем: filter=%D0%A2%D0%BE%D0%B2%D0%B0%D1%80%201&filter=%D0%A2%D0%BE%D0%B2%D0%B0%D1%80%202
Для интеграции с сайтами на PHP нам необходимо добавить квадратные скобки к имени параметра. Обратите внимание: сами скобки [] также требуют кодирования, превращаясь в %5B%5D.
МассивЗначений = Новый Массив;
МассивЗначений.Добавить(105);
МассивЗначений.Добавить(207);
// Кодируем имя параметра вместе со скобками
ИмяПараметраЗакодированное = КодироватьСтроку("filter[]", СпособКодированияСтроки.URLКодирование);
СтрокаПараметров = "";
Для Каждого Элемент Из МассивЗначений Цикл
Если СтрокаПараметров <> "" Тогда
СтрокаПараметров = СтрокаПараметров + "&";
КонецЕсли;
ЗначениеЗакодированное = КодироватьСтроку(Строка(Элемент), СпособКодированияСтроки.URLКодирование);
СтрокаПараметров = СтрокаПараметров + ИмяПараметраЗакодированное + "=" + ЗначениеЗакодированное;
КонецЦикла;
// На выходе получаем: filter%5B%5D=105&filter%5B%5D=207
Если сервер требует жесткой индексации элементов массива, мы можем использовать счетчик в цикле:
МассивЗначений = Новый Массив;
МассивЗначений.Добавить("Москва");
МассивЗначений.Добавить("Санкт-Петербург");
СтрокаПараметров = "";
Для Индекс = 0 По МассивЗначений.В Граница() Цикл
Если СтрокаПараметров <> "" Тогда
СтрокаПараметров = СтрокаПараметров + "&";
КонецЕсли;
// Формируем имя параметра вида: filter[0], filter[1] и т.д.
ИмяПараметраСИндексом = "filter[" + Формат(Индекс, "ЧГ=0") + "]";
ИмяПараметраЗакодированное = КодироватьСтроку(ИмяПараметраСИндексом, СпособКодированияСтроки.URLКодирование);
ЗначениеЗакодированное = КодироватьСтроку(Строка(МассивЗначений[Индекс]), СпособКодированияСтроки.URLКодирование);
СтрокаПараметров = СтрокаПараметров + ИмяПараметраЗакодированное + "=" + ЗначениеЗакодированное;
КонецЦикла;
Если принимающий сервис умеет самостоятельно парсить строки, разделенные запятыми, это значительно упрощает задачу на стороне 1С. Мы можем воспользоваться встроенным методом СтрСоединить().
МассивЗначений = Новый Массив;
МассивЗначений.Добавить("Элемент1");
МассивЗначений.Добавить("Элемент2");
// Объединяем элементы массива через запятую
СтрокаЭлементов = СтрСоединить(МассивЗначений, ",");
// Кодируем всю результирующую строку параметров
СтрокаПараметров = "filter=" + КодироватьСтроку(СтрокаЭлементов, СпособКодированияСтроки.URLКодирование);
// На выходе получаем: filter=%D0%AD%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%821%2C%D0%AD%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%822
Иногда документация к API требует передавать массив как единую сериализованную JSON-строку внутри GET-параметра. В 1С для сериализации объекта Массив используется ЗаписьJSON.
МассивЗначений = Новый Массив;
МассивЗначений.Добавить("ПараметрА");
МассивЗначений.Добавить("ПараметрБ");
// Записываем массив в JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивЗначений);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Кодируем полученный JSON для безопасной вставки в URL
СтрокаПараметров = "filter=" + КодироватьСтроку(СтрокаJSON, СпособКодированияСтроки.URLКодирование);
Давайте соберем рабочий пример отправки GET-запроса с параметром-массивом на базе встроенных механизмов платформы 1С. Будем использовать схему со скобками PHP-стиля.
Процедура ОтправитьЗапросНаСайт()
// 1. Инициализируем массив данных для отправки
МассивID = Новый Массив;
МассивID.Добавить(1001);
МассивID.Добавить(1002);
МассивID.Добавить(1003);
// 2. Сборка строки GET-параметров
ИмяПараметраЗакодированное = КодироватьСтроку("ids[]", СпособКодированияСтроки.URLКодирование);
СтрокаПараметров = "";
Для Каждого ТекID Из МассивID Цикл
Если СтрокаПараметров <> "" Тогда
СтрокаПараметров = СтрокаПараметров + "&";
КонецЕсли;
СтрокаПараметров = СтрокаПараметров + ИмяПараметраЗакодированное + "=" + КодироватьСтроку(Строка(ТекID), СпособКодированияСтроки.URLКодирование);
КонецЦикла;
// 3. Настройка HTTP-соединения и отправка запроса
Сервер = "api.mysite.ru";
АдресРесурса = "/v1/products?" + СтрокаПараметров;
// Создаем защищенное соединение SSL, если сайт работает по HTTPS
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеProperties();
HTTPСоединение = Новый HTTPСоединение(Сервер, 443,,,,, ЗащищенноеСоединение);
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса);
HTTPЗапрос.Заголовки.Вставить("Accept", "application/json");
Попытка
HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
Если HTTPОтвет.КодСостояния = 200 Тогда
Сообщить("Запрос успешно отправлен. Ответ сервера: " + HTTPОтвет.ПолучитьТелоКакСтроку());
Иначе
Сообщить("Ошибка сервера. Код состояния: " + HTTPОтвет.КодСостояния);
КонецЕсли;
Исключение
Сообщить("Не удалось установить связь с сервером: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
При передаче массивов через GET-параметры крайне важно помнить о физических ограничениях на длину URI (адресной строки запроса). Хотя в самом стандарте HTTP нет жесткого лимита на количество символов в URL, на практике ограничения накладывают сетевое оборудование, прокси-серверы и веб-серверы, обрабатывающие запросы на стороне сайта:
client_header_buffer_size). При превышении лимита сервер вернет ошибку 414 Request-URI Too Long.Рекомендация: Если ваш массив в 1С динамический и может содержать сотни или тысячи элементов (например, выгрузка большого списка ID номенклатуры), передавать его через GET-запрос категорически не рекомендуется. В такой ситуации необходимо переписать интеграцию на использование метода POST, упаковав весь массив в тело запроса в формате JSON. Это полностью снимет ограничения на размер передаваемых данных.
Что делать, если сторонняя документация API строго требует отправки именно GET-запроса, но размер вашего массива превышает допустимые 4-8 Кб веб-сервера? В некоторых современных веб-фреймворках реализована поддержка механизма подмены методов.
Вы можете отправить полноценный POST-запрос, поместив весь массив в тело запроса (в JSON-формате), но при этом добавить в заголовки запроса специальное указание для сервера трактовать данный запрос как GET:
HTTPЗапрос = Новый HTTPЗапрос("/v1/products");
// Подменяем метод POST на GET на уровне веб-сервера получателя
HTTPЗапрос.Заголовки.Вставить("X-HTTP-Method-Override", "GET");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
// Помещаем массив в тело запроса
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON);
Важно: Данный метод будет работать только в том случае, если разработчики принимающего веб-сервиса явно заложили поддержку заголовка X-HTTP-Method-Override (или аналогичного X-Method-Override) в архитектуру своего приложения.