Почему при отправке HTTP-запроса из 1С сервер возвращает пустой ответ?

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

При интеграции 1С со сторонними веб-сервисами (например, Zabbix API или другими службами на базе JSON-RPC) разработчики часто сталкиваются с ситуацией, когда проверенный через утилиту cURL или Postman запрос успешно выполняется, а аналогичный вызов из встроенного языка 1С возвращает пустой ответ или завершается с ошибкой. Разберем по шагам, почему так происходит, какие скрытые нюансы существуют при работе с объектами HTTPСоединение и HTTPЗапрос, и как правильно реализовать обмен.

Анализ типичных ошибок в исходном коде

Рассмотрим типовой сценарий: необходимо отправить POST-запрос с JSON-телом на веб-сервер. В процессе реализации часто допускаются неочевидные ошибки, которые приводят к искажению пакета данных:

  1. Некорректное имя заголовка в объекте Соответствие: если написать ЗаголовокЗапросаHTTP.Вставить("Content-Type: ", "application/json-rpc"), платформа 1С при формировании сетевого заголовка автоматически добавит разделительное двоеточие. На веб-сервер уйдет заголовок Content-Type: : application/json-rpc. Многие парсеры и веб-серверы отбрасывают такие заголовки, не понимая формат переданных данных. Имя заголовка в ключе соответствия должно быть строго без двоеточия и пробелов — "Content-Type".
  2. Использование маркера последовательности байтов (BOM): метод HTTPЗапрос.УстановитьТелоИзСтроки() по умолчанию может добавлять в начало потока байты BOM (Byte Order Mark). Многие веб-серверы и функции разбора JSON (например, стандартный json_decode в PHP) не могут обработать строку с BOM и признают JSON невалидным, возвращая ошибку 400 или пустой ответ.
  3. Синтаксические ошибки в литерале строки: ручная сборка JSON-строк через многострочные литералы с лишними круглыми скобками, переносами или неэкранированными кавычками легко приводит к нарушению формата.
  4. Избыточное использование временных файлов: сохранение ответа через промежуточный файл на диске с последующим чтением через ТекстовыйДокумент усложняет код и маскирует реальный код состояния HTTP-ответа.

Способ 1. Исправление прямого запроса и чтение ответа в память

Выясним причину проблем и перепишем код, исключив лишние дисковые операции. Объект HTTPОтвет, возвращаемый методами объекта HTTPСоединение, позволяет получить тело ответа напрямую в переменную типа Строка с помощью метода ПолучитьТелоКакСтроку(), а также проверить свойство КодСостояния.

Посмотрим на пример правильной отправки запроса с контролем заголовков и отключением BOM:


СерверПриемник = "zbx.ru";
АдресСтраницыНаСервере = "/api_jsonrpc.php"; // Рекомендуется указывать ведущий слэш
Таймаут = 120;

// Инициализируем соединение без указания протокола в имени сервера
HTTP = Новый HTTPСоединение(СерверПриемник, , , , , Таймаут);

// Формируем заголовки: имя заголовка указывается строго без двоеточия
Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "application/json-rpc");

HTTPЗапрос = Новый HTTPЗапрос(АдресСтраницыНаСервере, Заголовки);

// Формируем тело JSON без лишних обрамляющих скобок
СтрокаJSON = "{
|	""jsonrpc"": ""2.0"",
|	""method"": ""host.get"",
|	""params"": {""groupids"": ""45""},
|	""id"": 0,
|	""auth"": ""9a59f9d85ba01c2036bc59932a""
|}";

// Обязательно указываем кодировку UTF-8 и отключаем использование Byte Order Mark (BOM)
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

// Отправляем запрос и получаем ответ в память без промежуточных файлов
Ответ = HTTP.ОтправитьДляОбработки(HTTPЗапрос);

// Проверяем результат выполнения
Если Ответ.КодСостояния = 200 Тогда
	СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
	Сообщить(СтрокаОтвета);
Иначе
	Сообщить("Ошибка вызова сервиса. Код состояния: " + Ответ.КодСостояния);
	Сообщить("Тело ответа: " + Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8));
КонецЕсли;

Способ 2. Надежное формирование JSON через штатные средства платформы

Рассмотрим подробнее альтернативный и более надежный подход. Чтобы избежать ошибок форматирования кавычек, спецсимволов и управляющих конструкций в JSON-строках, рекомендуется формировать структуру данных во встроенном языке 1С и выполнять ее сериализацию при помощи объектов ЗаписьJSON и ЗаписатьJSON.

Разберем этот вариант по шагам:


// Шаг 1. Формируем структуру параметров запроса
ПараметрыЗапроса = Новый Структура();
ПараметрыЗапроса.Вставить("groupids", "45");

ТелоСтруктура = Новый Структура();
ТелоСтруктура.Вставить("jsonrpc", "2.0");
ТелоСтруктура.Вставить("method", "host.get");
ТелоСтруктура.Вставить("params", ПараметрыЗапроса);
ТелоСтруктура.Вставить("id", 0);
ТелоСтруктура.Вставить("auth", "9a59f9d85ba01c2036bc59932a");

// Шаг 2. Сериализуем структуру в JSON-строку
ЗаписьJSON = Новый ЗаписьJSON();
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
ЗаписатьJSON(ЗаписьJSON, ТелоСтруктура);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Шаг 3. Отправляем сформированные данные на сервер
HTTP = Новый HTTPСоединение("zbx.ru", , , , , 120);

Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "application/json-rpc");

HTTPЗапрос = Новый HTTPЗапрос("/api_jsonrpc.php", Заголовки);
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Ответ = HTTP.ОтправитьДляОбработки(HTTPЗапрос);

Если Ответ.КодСостояния = 200 Тогда
	СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
	
	// Шаг 4. Читаем ответ сервера в структуру
	ЧтениеJSON = Новый ЧтениеJSON();
	ЧтениеJSON.УстановитьСтроку(СтрокаОтвета);
	ДанныеОтвета = ПрочитатьJSON(ЧтениеJSON);
	ЧтениеJSON.Закрыть();
	
	// Теперь с результатом можно работать как с объектом Соответствие или Структура
Иначе
	ВызватьИсключение "Ошибка HTTP: " + Ответ.КодСостояния;
КонецЕсли;

Что важно помнить при отладке сетевых запросов в 1С

  1. Имя хоста: в первом параметре конструктора HTTPСоединение указывается только доменное имя или IP-адрес (например, "zbx.ru"). Указание префикса протокола вида "http://" является ошибкой и приводит к невозможности разрешения сетевого адреса.
  2. Протокол HTTPS: если целевой сервис работает по защищенному протоколу HTTPS, в конструктор HTTPСоединение необходимо передать порт 443 и объект ЗащищенноеСоединениеOpenSSL.
  3. HTTP-редиректы: в отличие от утилиты cURL с флагом следования за перенаправлениями, платформа 1С не переходит по редиректам (коды 301, 302) автоматически. Если сервер выполняет перенаправление на защищенный протокол или другой URL, 1С получит пустой ответ со статусом перенаправления, который необходимо отслеживать через Ответ.КодСостояния.
← На главную