Как отправить GET-запрос с телом (Request Body) в 1С:Предприятие

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

В процессе интеграции 1С с современными веб-сервисами разработчики периодически сталкиваются с нестандартными требованиями API сторонних систем. Одно из таких требований — передача параметров в формате JSON непосредственно в теле (Request Body) HTTP-запроса с методом GET. Классический пример — популярный поисковый движок Elasticsearch или специфические методы авторизации и получения статусов документов в коммерческих API.

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

Почему стандартные средства 1С не работают?

Давайте обратимся к теории веб-протоколов и логике платформы «1С:Предприятие». Согласно спецификации HTTP, метод GET предназначен для получения информации с сервера, и передача параметров традиционно должна происходить через строку запроса (URL Query Parameters). Хотя современные стандарты (в частности, RFC 9110) допускают наличие тела в GET-запросах при предварительной договоренности между клиентом и сервером, многие сетевые библиотеки и промежуточные узлы (прокси, фаерволы, балансировщики нагрузки) до сих пор принудительно отбрасывают тело таких запросов в целях безопасности.

Разработчики платформы 1С приняли консервативное решение и заблокировали эту возможность на уровне кода. Если мы откроем Синтакс-Помощник к объекту HTTPСоединение и его методам Получить() или универсальному ВызватьHTTPМетод(), мы увидим официальное примечание:

«При использовании метода GET тело запроса на сервер отправлено не будет.»

Даже если мы попытаемся использовать объект HTTPЗапрос и применить к нему метод УстановитьТелоИзСтроки(), при выполнении метода GET платформа 1С принудительно очистит отправляемый буфер данных. Использование сторонних популярных библиотек-оберток (например, «Коннектор» для 1С) также не принесет результата, поскольку под капотом они используют все те же стандартные платформенные объекты.

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

Решение 1. Кроссплатформенный запуск системной утилиты curl

Консольная утилита curl является стандартом де-факто для работы с сетевыми запросами в операционных системах Linux и современных версиях Windows 10/11 / Windows Server. Данная утилита умеет принудительно отправлять тело с любым HTTP-методом.

Рассмотрим алгоритм реализации этого подхода в коде 1С по шагам:

  1. Формируем необходимую структуру JSON в 1С.
  2. Записываем полученную строку во временный файл на диске.
  3. Формируем строку команды запуска curl, где указываем принудительный метод -X GET, путь к файлу с телом через параметр -d @ и файл для сохранения ответа сервера через -o.
  4. Запускаем приложение через команду ЗапуститьПриложение() в синхронном режиме.
  5. Считываем полученный файл ответа обратно в 1С и удаляем временные файлы.

Ниже представлен готовый пример кода, реализующий данный алгоритм:


// Шаг 1. Формируем JSON-структуру запроса
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("Id", "123456789");
СтруктураДанных.Вставить("Id_doc", "555");

ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(,,, ЭАП_Токен); // Если нужна спец-кодировка
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Шаг 2. Создаем временные файлы
ИмяФайлаЗапроса = ПолучитьИмяВременногоФайла("json");
ИмяФайлаОтвета = ПолучитьИмяВременногоФайла("json");

// Записываем JSON во временный файл в кодировке UTF-8 без BOM
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаЗапроса, КодировкаТекста.UTF8, СимволыВСтроке.Нет, Ложь);
ЗаписьТекста.Записать(СтрокаJSON);
ЗаписьТекста.Закрыть();

// Шаг 3. Сборка команды для curl
// Флаг -s отключает индикатор прогресса curl в консоли
URLПодключения = "https://your-api-domain.com/api/getStatus";
СтрокаКоманды = "curl -s -X GET """ + URLПодключения + """ "
              + "-H ""Content-Type: application/json"" "
              + "-d @" + """" + ИмяФайлаЗапроса + """ "
              + "-o " + """" + ИмяФайлаОтвета + """";

// Шаг 4. Запуск утилиты в режиме ожидания завершения
КодВозврата = Неопределено;
ЗапуститьПриложение(СтрокаКоманды,, Истина, КодВозврата);

// Шаг 5. Обработка результатов
Если КодВозврата = 0 Тогда
    ЧтениеТекста = Новый ЧтениеТекста(ИмяФайлаОтвета, КодировкаТекста.UTF8);
    СтрокаОтвета = ЧтениеТекста.Прочитать();
    ЧтениеТекста.Закрыть();
    
    // Выводим полученный ответ сервера
    Сообщить(СтрокаОтвета);
Иначе
    ВызватьИсключение "Ошибка при выполнении запроса через curl. Код возврата: " + КодВозврата;
КонецЕсли;

// Очистка временных файлов
УдалитьФайлы(ИмяФайлаЗапроса);
УдалитьФайлы(ИмяФайлаОтвета);

Этот способ является наиболее надежным, так как работает одинаково хорошо и на Windows-серверах, и на серверах под управлением Linux.

Решение 2. Использование COM-объекта MSXML2.ServerXMLHTTP (Только для Windows)

На форумах часто советуют использовать стандартный системный Windows-компонент WinHttp.WinHttpRequest.5.1. Однако будьте осторожны: библиотека WinHTTP на уровне операционной системы Microsoft Windows ведет себя аналогично платформе 1С — она автоматически очищает тело запроса, если в методе open() указан верб "GET".

Чтобы обойти это системное ограничение в среде Windows, мы можем использовать другой COM-объект — MSXML2.ServerXMLHTTP.6.0. Этот компонент более лоялен к стандартам и позволяет передать строку с телом в метод send() даже при использовании GET-запроса.

Проанализируем пример кода с использованием этого объекта:


// Способ работает только в среде ОС Windows
#Если Клиент Или НаСервере Тогда
Если Найти(ВРег(СистемнаяИнформация.ОперационнаяСистема), "WINDOWS") > 0 Тогда

    URL = "https://your-api-domain.com/api/getStatus";
    СтрокаJSON = "[{""Id"": ""123456789"", ""Id_doc"": ""555""}]";

    Попытка
        HttpReq = Новый COMОбъект("MSXML2.ServerXMLHTTP.6.0");
        HttpReq.open("GET", URL, Ложь); // Ложь — для синхронного выполнения
        HttpReq.setRequestHeader("Content-Type", "application/json");
        HttpReq.setRequestHeader("Accept", "application/json");
        
        // Отправляем запрос, передавая JSON непосредственно в параметры метода send
        HttpReq.send(СтрокаJSON);
        
        Если HttpReq.status = 200 Тогда
            СтрокаОтвета = HttpReq.responseText;
            Сообщить("Ответ сервера: " + СтрокаОтвета);
        Иначе
            Сообщить("Ошибка сервера: " + HttpReq.status + " " + HttpReq.statusText);
        КонецЕсли;
    Исключение
        Сообщить("Не удалось выполнить запрос через MSXML2.ServerXMLHTTP: " + ОписаниеОшибки());
    КонецПопытки;

Иначе
    Сообщить("Данный способ доступен только для операционной системы Windows!");
КонецЕсли;
#КонецЕсли

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

Решение 3. Использование промежуточного микро-прокси (Архитектурный подход)

Если запросы к API выполняются интенсивно (десятки тысяч запросов в час), постоянный вызов внешней утилиты curl через операционную систему может создавать избыточную нагрузку на процессор сервера 1С. В таком случае идеальным архитектурным решением станет создание небольшого промежуточного прокси-скрипта (веб-хука) на вашем веб-сервере.

Скрипт пишется буквально в несколько строк на любом удобном языке программирования (PHP, Python, Node.js). Схема работы выглядит следующим образом:

  1. 1С отправляет на ваш внутренний веб-сервер стандартный и полностью легитимный POST-запрос, в тело которого помещает целевой JSON и адрес внешнего API.
  2. Промежуточный веб-сервер принимает этот POST-запрос, извлекает тело и адрес назначения.
  3. Скрипт на сервере (используя библиотеку, которая позволяет отправлять GET с телом, например requests на Python или cURL на PHP) выполняет реальный GET-запрос к внешнему API.
  4. Полученный результат прокси-сервер транслирует обратно в 1С в качестве ответа на исходный POST-запрос.

Такой подход полностью решает проблему производительности и избавляет код 1С от зависимости от системных утилит или COM-объектов операционной системы, сохраняя код конфигурации чистым и кроссплатформенным.

← На главную