Как правильно настроить HTTP-запрос в 1С, исправить ошибку Couldn't resolve host name и отправить XML или JSON

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

Работа с веб-сервисами и сторонними API через HTTP-запросы — одна из самых частых задач современного разработчика 1С. Однако при первой встрече с объектами HTTPСоединение и HTTPЗапрос легко совершить типовые ошибки, которые приводят к падению программы. Одной из таких классических ошибок является системное сообщение "Ошибка работы с Интернет: Couldn't resolve host name".

В этой статье мы подробно разберем, почему возникает эта ошибка, научимся правильно разделять адрес сервера и параметры запроса, разберемся с безопасным соединением HTTPS, настроим авторизацию и рассмотрим лучшие практики отправки файлов XML и JSON.

Причина ошибки "Couldn't resolve host name" и правильное разделение адреса

Давайте проанализируем код, с которого часто начинают новички:


// Ошибочный код
Запрос = "";
HTTPЗапрос = Новый HTTPЗапрос("http://iskander.mstarproject.com/?action=exchange&type=sale&mode=checkauth");
HTTPСоединение = Новый HTTPСоединение("http://iskander.mstarproject.com/?action=exchange&type=sale&mode=checkauth");
Ответ = HTTPСоединение.Получить(HTTPЗапрос);

При выполнении этого кода платформа выдает ошибку сопоставления имени хоста. Выясним причину этой проблемы. Объект HTTPСоединение предназначен для установления канала связи с сервером, а объект HTTPЗапрос — для описания конкретного обращения к ресурсу внутри этого канала.

Правило 1: В конструктор HTTPСоединение в качестве первого параметра (сервера) передается исключительно имя домена или IP-адрес. Указывать протокол (http:// или https://) перед именем хоста категорически нельзя! DNS-клиент платформы не сможет распознать такую строку и выдаст ошибку "Couldn't resolve host name".

Правило 2: Путь к конкретному ресурсу (скрипту, методу API) и GET-параметры (все, что идет после символа вопроса ?) должны передаваться в конструктор объекта HTTPЗапрос.

Рассмотрим, как правильно переписать этот фрагмент кода:


// Правильное разделение хоста и ресурса
АдресСервера = "iskander.mstarproject.com";
ПутьКРесурсу = "/?action=exchange&type=sale&mode=checkauth";

HTTPСоединение = Новый HTTPСоединение(АдресСервера);
HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);

Переход на защищенное соединение (HTTPS)

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

Для работы с HTTPS необходимо использовать объект ЗащищенноеСоединениеOpenSSL. Посмотрим на пример инициализации безопасного соединения:


АдресСервера = "iskander.mstarproject.com";
ПутьКРесурсу = "/?action=exchange&type=sale&mode=checkauth";

// Инициализируем защищенное соединение с использованием сертификатов операционной системы
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();

// Передаем защищенное соединение в конструктор в качестве седьмого параметра
HTTPСоединение = Новый HTTPСоединение(АдресСервера, 443, , , , , ЗащищенноеСоединение);
HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);

Использование порта 443 и объекта защиты гарантирует шифрование трафика и успешное прохождение рукопожатия (SSL handshake) с сервером.

Авторизация запроса: передача логина и пароля

Если веб-ресурс требует базовую авторизацию (Basic Authentication), учетные данные необходимо передавать в конструктор объекта HTTPСоединение. Обратите внимание на правильный порядок параметров:

  1. Сервер (хост)
  2. Порт (необязательно, для HTTPS обычно 443)
  3. Пользователь (логин)
  4. Пароль

Если перепутать порядок (например, сначала написать пароль, а потом логин), сервер вернет ошибку "401 Unauthorized" или "Access denied".


Логин = "MyUser";
Пароль = "MySecretPassword";

// Правильная инициализация с авторизацией
HTTPСоединение = Новый HTTPСоединение(АдресСервера, 443, Логин, Пароль, , , ЗащищенноеСоединение);

Смена HTTP-метода (GET vs POST/PUT)

Часто разработчики совершают логическую ошибку, пытаясь отправить данные на сервер методом Получить(). На уровне протокола HTTP метод GET (который вызывается через Получить) не должен нести в себе тело запроса (payload). Некоторые веб-серверы принудительно очищают тело GET-запроса или блокируют его.

Если ваша задача — передать файл или строку данных (XML, JSON) на сервер, используйте другие методы:

Посмотрим, как меняется вызов в коде:


// Вместо: Ответ = HTTPСоединение.Получить(HTTPЗапрос);
// Используем для отправки данных:
Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);

Как правильно отправить XML или JSON-данные

На форумах часто советуют сомнительные архитектурные решения — например, оборачивать весь XML-файл внутрь JSON-строки. В реальной практике так делать не нужно. Рассмотрим два стандартных и максимально эффективных способа отправки XML на сервер.

Способ А. Отправка файла напрямую с диска (рекомендуется для больших XML)

Если XML-файл уже сформирован и сохранен на жестком диске, считывать его целиком в оперативную память сервера в виде строки нецелесообразно — это может вызвать перегрузку памяти при больших объемах выгрузки. В 1С предусмотрен метод УстановитьИмяФайлаТела(), который позволяет передать файл "потоком" напрямую с диска:


HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);

// Указываем путь к локальному файлу XML
ПутьКФайлу = "C:\temp\export_data.xml";
HTTPЗапрос.УстановитьИмяФайлаТела(ПутьКФайлу);

// Обязательно сообщаем серверу тип передаваемого контента
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/xml; charset=utf-8");

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

Способ Б. Отправка XML из строки (без записи на диск)

Если вы генерируете XML динамически в коде с помощью объекта ЗаписьXML, записывать его на диск необязательно. Вы можете преобразовать его в строку и передать в тело запроса:


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();

// Пример формирования структуры XML
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("data");
ЗаписьXML.ЗаписатьТекст("Привет, веб-сервер!");
ЗаписьXML.ЗаписатьКонецЭлемента();

СтрокаXML = ЗаписьXML.Закрыть(); // Получаем готовую строку XML

HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаXML, КодировкаТекста.UTF8);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/xml; charset=utf-8");

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

Отправка данных в формате JSON

Если ваше API требует передачи данных в формате JSON, то логика остается точно такой же, меняется только заголовок Content-Type и способ формирования строки:


// Формируем структуру данных
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("action", "exchange");
СтруктураДанных.Вставить("type", "sale");

// Сериализуем структуру в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();

HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8);

// Указываем заголовок для JSON
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

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

Настройка заголовков (Content-Type)

Никогда не забывайте добавлять заголовки к запросу. Без явного указания Content-Type принимающий веб-сервер не сможет понять, как обрабатывать полученный массив байтов — как текст, файл или структуру данных. Это может привести к ошибкам "400 Bad Request" или "500 Internal Server Error".

Анализ ответов сервера и обработка ошибок

Чтобы ваше интеграционное решение было стабильным и отказоустойчивым, всегда анализируйте код состояния (status code), который возвращает сервер. Ошибки семейства 4xx (например, 404 — ресурс не найден) и 5xx (ошибка сервера) должны обрабатываться программно, чтобы не вызывать аварийного завершения работы у конечного пользователя.

Разберем пример комплексной обработки результата HTTP-запроса:


Попытка
    Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
    КодCостояния = Ответ.КодСостояния;
    
    Если КодCостояния >= 200 И КодCостояния < 300 Тогда
        // Успешный запрос
        ТекстОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
        Сообщить("Данные успешно отправлены! Ответ сервера: " + ТекстОтвета);
    ИначеЕсли КодCостояния = 401 Или КодCостояния = 403 Тогда
        Сообщить("Ошибка авторизации! Проверьте логин и пароль.");
    ИначеЕсли КодCостояния = 404 Тогда
        Сообщить("Запрашиваемый ресурс не найден на веб-сервере. Проверьте путь.");
    Иначе
        Сообщить("Сервер вернул ошибку с кодом: " + КодCостояния);
        ТекстОшибки = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
        Сообщить("Детали ошибки: " + ТекстОшибки);
    КонецЕсли;
    
Исключение
    // Сюда программа попадет, если возникли сетевые проблемы (например, нет интернета)
    ИнформацияОбОшибке = ИнформацияОбОшибке();
    Сообщить("Произошла сетевая ошибка при подключении к серверу: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке));
КонецПопытки;

Используя предложенный шаблон, вы сможете гарантировать корректное поведение программы в любых внештатных ситуациях: от отсутствия интернета у клиента до ошибок на стороне внешнего API.

← На главную