Работа с HTTP-запросами в 1С: получение и отправка тела запроса

Бесплатная консультация юриста

+7 (800) 302-87-29

Реклама jurik.ru

Работа с HTTP-запросами — базовая задача при интеграции 1С с внешними системами (REST API, веб-сервисы, обмен данными). Под «получением тела запроса» обычно понимают две разные задачи в зависимости от роли 1С:

  • Клиентская сторона (1С как потребитель API): как сформировать и отправить тело запроса (POST, PUT, PATCH).
  • Серверная сторона (1С как веб-сервис/HTTP-сервис): как прочитать и разобрать тело входящего запроса.

Ниже подробно разобраны оба сценария с примерами кода для платформы 1С:Предприятие 8.3 (актуально для 8.2 с учетом отличий в клиентском/серверном контексте).


1С выступает в роли HTTP-клиента (Отправка тела запроса)

Здесь «получение» подразумевает подготовку объекта HTTPЗапрос и заполнение его тела данными перед отправкой через HTTPСоединение.

Основные методы класса HTTPЗапрос для работы с телом

  • УстановитьТелоИзСтроки(<Строка>, <Кодировка>, <Content-Type>) — универсальный способ передать JSON, XML, обычный текст.
  • УстановитьТелоИзДвоичныхДанных(<ДвоичныеДанные>, <Content-Type>) — для отправки файлов, картинок, бинарных протоколов.
  • УстановитьТелоИзПотока(<ПотокЧтения>, <Content-Type>) — для больших объемов данных (потоковая передача без загрузки всего в память).

Пример: Отправка JSON (REST API)

Самый частый сценарий — POST запрос с JSON-телом.

// Пример процедуры на клиенте (или на сервере без UI)
Процедура ОтправитьJSONНаСервер
 
 // 1. Подготовка данных для отправки
 СтруктураДанных = Новый Структура;
 СтруктураДанных.Вставить("userId", 123);
 СтруктураДанных.Вставить("action", "create_order");
 СтруктураДанных.Вставить("items", Новый Массив({"Товар 1", "Товар 2"}));
 
 // Сериализация в JSON
 ЗаписьJSON = Новый ЗаписьJSON;
 ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(, Истина)); // Истина = читаемый формат (с отступами)
 ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
 JSONСтрока = ЗаписьJSON.Закрыть;
 
 // 2. Настройка соединения (HTTPS требует защищенное соединение)
 // Для работы с HTTPS на сервере 1С может потребоваться настройка сертификатов (ca-certificates)
 Соединение = Новый HTTPСоединение(
 "api.example.com", // Хост
 443, // Порт (443 для HTTPS)
 , , , // Пользователь, Пароль, Прокси (если нужны)
 30, // Таймаут в секундах
 Новый ЗащищенноеСоединениеOpenSSL // Для HTTPS
 );
 
 // 3. Формирование запроса
 Запрос = Новый HTTPЗапрос("/v1/orders");
 Запрос;Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
 Запрос.Заголовки.Вставить("Accept", "application/json");
 // Авторизация (если нужна Bearer токен)
 // Запрос.Заголовки.Вставить("Authorization", "Bearer " + ВашТокен);
 
 // 4. УСТАНОВКА ТЕЛА ЗАПРОСА
 Запрос.УстановитьТелоИзСтроки(JSONСтрока, КодировкаТекста.UTF8, "application/json");
 
 // 5. Отправка (POST)
 Попытка
 Результат = Соединение.ОтправитьДляОбработки(Запрос); // Асинхронно (только клиент) 
 // ИЛИ синхронно (на сервере и клиенте):
 // Результат = Соединение.Выполнить(Запрос); // Для POST используйте Выполнить или Получить с методом POST
 // Внимание: Метод Получить всегда делает GET. Для POST используйте:
 Результат = Соединение.Выполнить(Запрос); // В новых версиях платформы
 // В старых версиях (8.2, ранние 8;3) для POST использовали недокументированные способы или COM, 
 // но современный способ: Соединение.Выполнить(Запрос) где Запрос уже содержит тело -> платформа сама делает POST.
 
 // Проверка результата
 Если Результат.КодСостояния = 200 ИЛИ Результат.КодСостояния = 201 Тогда
 ОтветСтрока = Результат.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
 Сообщить("Успешно: " + ОтветСтрока);
 Иначе
 Сообщить("Ошибка HTTP: " + Результат.КодСостояния + " ⎯ " + Результат.ПолучитьТелоКакСтроку);
 КонецЕсли;
 
 Исключение
 Сообщить("Ошибка связи: " + ОписаниеОшибки);
 КонецПопытки;
 
КонецПроцедуры

> Важно: В современных версиях платформы (8.3.18+) метод HTTPСоединение.Выполнить(HTTPЗапрос) автоматически определяет метод (GET/POST/PUT) по наличию тела в запросе. Если тело есть — отправляется POST (или PUT/PATCH, если задано свойство Запрос.Метод = "PUT").

Пример: Отправка файла (multipart/form-data)

Для загрузки файлов стандартный HTTPЗапрос не имеет встроенного сборщика multipart. Нужно формировать тело вручную или использовать сторонние библиотеки (например, OneHttp). Пример ручного формирования:

Процедура ОтправитьФайлMultipart
 Граница = "----WebKitFormBoundary" + СтрЗаменить(Новый УникальныйИдентификатор, "-", "");
 
 Поток = Новый ЗаписьТекста(Новый ПотокВПамяти, КодировкаТекста.UTF8);
 
 // Часть 1: обычное поле
 Поток.ЗаписатьСтроку("--" + Граница);
 Поток.ЗаписатьСтроку("Content-Disposition: form-data; name=""description""");
 Поток.ЗаписатьСтроку("Content-Type: text/plain; charset=utf-8");
 Поток.ЗаписатьСтроку("");
 Поток.ЗаписатьСтроку("Описание моего файла");
 
 // Часть 2: файл
 Поток.ЗаписатьСтроку("--" + Граница);
 Поток.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""test.txt""");
 Поток.ЗаписатьСтроку("Content-Type: text/plain");
 Поток.ЗаписатьСтроку("");
 
 // Получаем двоичные данные заголовков
 ДвоичныеЗаголовки = Поток.Поток.ПолучитьДвоичныеДанные;
 
 // Читаем файл
 ДанныеФайла = ПолучитьДвоичныеДанныеИзФайла("C:	emp	est.txt");
  // Закрывающая граница
 КонецТела = ПолучитьДвоичныеДанныеИзСтроки(Символы.ПС + "--" + Граница + "--" + Символы.ПС, КодировкаТекста.UTF8);
 
 // Собираем всё в один поток/двоичные данные
 Запрос = Новый HTTPЗапрос("/upload");
 // ... отправка через Соединение.Выполнить(Запрос)
КонецПроцедуры

1С выступает в роли HTTP-сервиса (Чтение тела входящего запроса)

Это сценарий публикации HTTP-сервисов (расширение конфигурации `HTTPСервисы`) или REST-интерфейса. Код выполняется на сервере 1С (в контексте сеанса веб-сервиса).

Где доступен запрос?

В модуле менеджера HTTP-сервиса (или модуле объекта REST) доступен параметр Запрос типа HTTPЗапросВходящий.

Чтение тела как строки (JSON, XML, Text)

Метод ПолучитьТелоКакСтроку считывает весь поток в память. Подходит для небольших и средних запросов (до десятков МБ).

// Функция обработки POST запроса в модуле HTTP-сервиса
Функция ОбработатьЗаказ(Запрос, Ответ)
 
 // 1. Проверка метода
 Если Запрос.Метод <> "POST" Тогда
 Ответ.КодСостояния = 405; // Method Not Allowed
 Ответ.УстановитьТелоИзСтроки("Метод не поддерживается");
 Возврат;
 КонецЕсли;
 
 // 2. Проверка Content-Type (опционально, но рекомендуется)
 ContentType = Запрос.Заголовки.Получить("Content-Type");
 ЕстьJSON = (ContentType <> Неопределено) И (Найти(ContentType, "application/json") > 0);
 
 // 3. Чтение тела
 Попытка
 // Важно: Поток можно прочитать ТОЛЬКО ОДИН РАЗ!
 ТелоСтроки = Запрос.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
 Исключение
 Ответ.КодСостояния = 400;
 Ответ.УстановитьТелоИзСтроки("Ошибка чтения тела: " + ОписаниеОшибки);
 Возврат;
 КонецПопытки;
  Если ПустаяСтрока(ТелоСтроки) Тогда
 Ответ.КодСостояния = 400;
 Ответ.УстановитьТелоИзСтроки("Пустое тело запроса");
 Возврат;
 КонецЕсли;
 
 // 4. Парсинг JSON
 Если ЕстьJSON Тогда
 Попытка
 ЧтениеJSON = Новый ЧтениеJSON;
 ЧтениеJSON.УстановитьСтроку(ТелоСтроки);
 ДанныеЗаказа = ПрочитатьJSON(ЧтениеJSON); // В структуру/массив/значение
 
 // Бизнес-логика: СоздатьЗаказ(ДанныеЗаказа)...
 IDЗаказа = СоздатьЗаказВБД(ДанныеЗаказа);
 
 Ответ.КодСостояния = 201;
 Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
 Ответ.УстановитьТелоИзСтроки("{"orderId": " + IDЗаказа + ", "status": "created"}");
 
 Исключение
 Ответ.КодСостояния = 400;
 Ответ.УстановитьТелоИзСтроки("Неверный JSON: " + ОписаниеОшибки);
 КонецПопытки;
 Иначе
 // Обработка XML, form-data и т.д.
 Ответ.КодСостояния = 415; // Unsupported Media Type
 Ответ.УстановитьТелоИзСтроки("Поддерживается только application/json");
 КонецЕсли;
 
КонецФункции

Потоковое чтение (Для больших файлов / экономии памяти)

Если ожидаются большие загрузки (десятки/сотни МБ), чтение в строку вызовет переполнение памяти; Используйте ПолучитьТелоКакПотокЧтения.

Функция ЗагрузитьБольшойФайл(Запрос, Ответ)
 
 // Получаем поток чтения (не загружает всё в ОЗУ)
 ПотокЧтения = Запрос.ПолучитьТелоКакПотокЧтения;
 
 // Определяем имя файла из заголовков (Content-Disposition) или генерируем
 ИмяФайла = ПолучитьИмяФайлаИзЗаголовков(Запрос.Заголовки);
 ПутьХранения = КаталогВременныхФайлов + ИмяФайла;
 
 // Записываем поток в файл по кускам (буферизированно)
 ЗаписьДвоичных = Новый ЗаписьДвоичныхДанных(ПутьХранения);
 Буфер = Новый ДвоичныеДанные(1024 * 1024); // Буфер 1 МБ
 
 Пока ПотокЧтения.Прочитать(Буфер) > 0 Цикл
 ЗаписьДвоичных.Записать(Буфер);
 КонецЦикла;
 
 ЗаписьДвоичных.Закрыть;
 ПотокЧтения.Закрыть; // Обязательно закрываем входящий поток
  // Дальше работаем с файлом ПутьХранения (перемещаем в хранилище, регистрируем в ИБ и т.д.)
 
 Ответ.КодСостояния = 200;
 Ответ.УстановитьТелоИзСтроки("Файл загружен: " + ИмяФайла);
 
КонецФункции

Обработка multipart/form-data (Загрузка файлов через формы)

Платформа 1С не имеет встроенного парсера multipart для входящих запросов. Вам придется парсить поток вручную или использовать готовые решения (библиотеки).

Алгоритм ручного парсинга:

  1. Получить `boundary` из заголовка `Content-Type` (например: `multipart/form-data; boundary=—-WebKitFormBoundaryABC123`).
  2. Получить поток: `Поток = Запрос.ПолучитьТелоКакПотокЧтения;`.
  3. Читать поток построчно/по байтам, искать разделитель `—boundary`.
  4. Парсить заголовки каждой части (Content-Disposition, Content-Type).
  5. Вычитывать тело части в файл или строку до следующего разделителя.

Рекомендация: Используйте проверенные открытые библиотеки (например, модуль `MultipartParser` из проекта oscript-library/http-client адаптированный для 1С, или аналогичные решения на Инфостарте), чтобы не изобретать велосипед и корректно обрабатывать кодировки и переносы строк.


Типичные ошибки и лучшие практики

Проблема Причина Решение
Пустое тело на сервере Поток `Запрос.ПолучитьТелоКакСтроку` или `ПолучитьТелоКакПотокЧтения` можно прочитать только один раз. Если вызвали дважды — второй раз будет пусто. Читайте тело в переменную сразу при входе в функцию и работайте с переменной.
Кривые кириллица / кодировка Клиент прислал в UTF-8, а сервер прочитал в ANSI (или наоборот). Заголовок `Content-Type` не содержит `charset`. Явно указывайте `КодировкаТекста.UTF8` в `ПолучитьТелоКакСтроку(КодировкаТекста.UTF8)`. На клиенте всегда ставьте `charset=utf-8` в заголовке.
Ошибка «Connection reset» / Timeout на клиенте Сервер долго обрабатывает запрос, а клиент разорвал соединение по таймауту (по умолчанию часто 30-60 сек). Увеличьте таймаут в `HTTPСоединение` (последний параметр конструктора). Для долгих операций используйте асинхронный паттерн: вернуть 202 Accepted + ID задачи, клиент опрашивает статус.
413 Payload Too Large Веб-сервер (IIS/Apache/Nginx) или платформа 1С обрезают большие тела. Настройте `maxAllowedContentLength` (IIS), `client_max_body_size` (Nginx), `LimitRequestBody` (Apache). В 1С (web-сервер) лимиты настраиваются в `default.vrd` (``).
Метод GET с телом Стандарт HTTP не запрещает тело у GET, но многие прокси/файрволы его отбрасывают. Для передачи сложных фильтров используйте POST (в теле JSON с фильтрами) или передавайте параметры в Query String (URL).

Резюме: Шпаргалка по методам

Клиент (Исходящий запрос: HTTPЗапрос)

  • Запрос.УстановитьТелоИзСтроки(Строка, Кодировка, ContentType) — JSON, XML, Text.
  • Запрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные, ContentType) — Файлы, бинарные данные.
  • Запрос.УстановитьТелоИзПотока(ПотокЧтения, ContentType) — Большие данные без копирования в память.
  • Запрос.Метод = «POST» / «PUT» / «PATCH» / «DELETE» — Явная установка метода (если автоопределение не срабатывает).
  • Соединение.Выполнить(Запрос) — Универсальный метод отправки (синхронный).

Сервер (Входящий запрос: HTTPЗапросВходящий)

  • Запрос.ПолучитьТелоКакСтроку(Кодировка) — Прочитать всё в строку (малые/средние данные).
  • Запрос.ПолучитьТелоКакДвоичныеДанные — Прочитать всё в двоичные данные.
  • Запрос.ПолучитьТелоКакПотокЧтения — Получить поток для поточной обработки (большие файлы).
  • Запрос.Заголовки.Получить(«Content-Type») — Определение формата данных.
  • Запрос.Метод — «GET», «POST», «PUT» и т.д.

Совет: При разработке интеграций всегда логируйте входящие заголовки и первые 100- тела (если это не секретные данные) в регистрацию 1С или внешнюю систему логирования (ELK, Grafana Loki). Это экономит часы отладки при ошибках «у клиента не работает».