При разработке интеграций с внешними веб-сервисами через протокол HTTP программисты часто сталкиваются с путаницей в синтаксисе метода ОтправитьДляОбработки(). Это связано с тем, что платформа 1С претерпела значительные изменения в части работы с HTTP-протоколом, начиная с версии 8.3.5. В этой статье мы подробно разберем, как адаптировать код под разные версии платформы, какие объекты использовать и как избежать типичных ошибок при выполнении POST-запросов.
Разберем ситуацию: в старых версиях платформы (до 8.2.17 и в ранних 8.3) метод ОтправитьДляОбработки() работал исключительно с файловой системой. Мы должны были сначала записать тело запроса во временный файл, а затем передать путь к нему в метод. Результат также сохранялся в файл.
С выходом версии 8.3.5 появилась объектная модель. Теперь вместо путей к файлам мы оперируем объектами HTTPЗапрос и HTTPОтвет. Однако, если ваша конфигурация запущена в режиме совместимости (например, 8.2.13 или 8.3.3), новый синтаксис может быть недоступен или работать некорректно. Рассмотрим оба варианта реализации.
Проанализируем работу с использованием объектной модели. Этот способ является наиболее предпочтительным, так как он избавляет от лишних манипуляций с файловой системой и позволяет гибко управлять заголовками. Рассмотрим пример формирования запроса:
// 1. Устанавливаем соединение
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL;
Соединение = Новый HTTPСоединение("api.service.ru", , , , , , ЗащищенноеСоединение);
// 2. Формируем объект запроса
Ресурс = "/v1/data/send";
Запрос = Новый HTTPЗапрос(Ресурс);
// 3. Устанавливаем заголовки и тело
Запрос.Заголовки.Вставить("Content-Type", "application/json");
СтрокаJSON = "{""id"": 123, ""action"": ""test""}";
Запрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// 4. Отправляем запрос и получаем объект ответа
Попытка
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Сообщить("Код состояния: " + Ответ.КодСостояния);
Сообщить("Ответ сервера: " + ТекстОтвета);
Исключение
Сообщить("Ошибка при отправке: " + ИнформацияОбОшибке().Описание);
КонецПопытки;
В данном примере метод УстановитьТелоИзСтроки автоматически управляет кодировкой. Важно обратить внимание на параметр ИспользованиеByteOrderMark. Многие современные API не принимают префикс BOM в UTF-8, поэтому рекомендуется устанавливать значение НеИспользовать.
Если ваша информационная база работает в режиме совместимости с версиями ниже 8.3.5, вам придется использовать классический "файловый" синтаксис. Выясним, как правильно передать параметры в этом случае. Синтаксис метода выглядит так: ОтправитьДляОбработки(ИмяФайлаЗапроса, АдресРесурса, ИмяФайлаРезультата, Заголовки).
Рассмотрим пример функции-обертки, которая эмулирует работу нового метода на старом движке:
Функция ОтправитьЗапросСтарымСпособом(Соединение, АдресРесурса, ДанныеСтрокой, ЗаголовкиСтруктурой)
// Создаем временный файл для тела запроса
ИмяФайлаЗапроса = ПолучитьИмяВременногоФайла();
ТекстЗапроса = Новый ЗаписьТекста(ИмяФайлаЗапроса, КодировкаТекста.UTF8, , Ложь);
ТекстЗапроса.Записать(ДанныеСтрокой);
ТекстЗапроса.Закрыть();
// Подготавливаем файл для ответа
ИмяФайлаРезультата = ПолучитьИмяВременногоФайла();
// Преобразуем заголовки из структуры в строку (требование старого синтаксиса)
СтрокаЗаголовков = "";
Для Каждого КлючИЗначение Из ЗаголовкиСтруктурой Цикл
СтрокаЗаголовков = СтрокаЗаголовков + КлючИЗначение.Ключ + ": " + КлючИЗначение.Значение + Символы.ПС;
КонецЦикла;
Попытка
// В старом синтаксисе метод не возвращает объект, а пишет в файл
Соединение.ОтправитьДляОбработки(ИмяФайлаЗапроса, АдресРесурса, ИмяФайлаРезультата, СтрокаЗаголовков);
// Читаем результат
ЧтениеОтвета = Новый ТекстовыйДокумент;
ЧтениеОтвета.Прочитать(ИмяФайлаРезультата, КодировкаТекста.UTF8);
Результат = ЧтениеОтвета.ПолучитьТекст();
Исключение
Результат = "Ошибка: " + ИнформацияОбОшибке().Описание;
КонецПопытки;
// Обязательно удаляем временные файлы
УдалитьФайлы(ИмяФайлаЗапроса);
УдалитьФайлы(ИмяФайлаРезультата);
Возврат Результат;
КонецФункции
Проанализируем ситуацию, когда при каждом запросе в цикле на стороне сервера (особенно если это база 1С) создаются новые сеансы (таблица Sysusersession в SQL). Это происходит, если объект HTTPСоединение инициализируется заново внутри цикла.
Рекомендация: создавайте объект HTTPСоединение один раз перед началом цикла обработки данных. 1С поддерживает механизм Keep-Alive, который позволяет использовать одно и то же TCP-соединение для последовательных запросов. Это не только снизит нагрузку на SQL-сервер, но и существенно ускорит работу обработки, так как исключит затраты времени на повторное рукопожатие (handshake) и авторизацию.
При отправке очень больших объемов данных (например, выгрузка файлов или тяжелых XML) использование метода УстановитьТелоИзСтроки() может привести к чрезмерному потреблению оперативной памяти и даже к падению рабочего процесса.
Выясним, как оптимизировать этот процесс. Даже в новом синтаксисе (8.3.5+) у объекта HTTPЗапрос есть метод УстановитьИмяФайлаТела(). Рассмотрим алгоритм:
ЗаписьXML или ЗаписьТекста).HTTPЗапрос.УстановитьИмяФайлаТела().ОтправитьДляОбработки().В этом случае платформа будет считывать данные порциями из файла прямо в сетевой поток, не загружая весь объем в память сервера приложений.
Метод ОтправитьДляОбработки() является синхронным. Это означает, что поток исполнения будет заблокирован до момента получения ответа или истечения времени ожидания. Рассмотрим важные параметры конструктора HTTPСоединение:
ИнтернетПрокси, иначе запрос может завершиться с ошибкой "Хост не найден".Ответ.КодСостояния. Успешными считаются коды в диапазоне 200–299. Коды 4xx и 5xx означают ошибки клиента или сервера соответственно.Подведем итог: выбор синтаксиса ОтправитьДляОбработки() напрямую зависит от вашего режима совместимости. Для современного кода всегда используйте HTTPЗапрос, а для поддержки старых систем — файловый метод с обязательной очисткой временных данных.