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

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

При интеграции 1С с внешними веб-сервисами разработчики нередко сталкиваются с ситуацией: сформированный URL прекрасно открывается в интернет-браузере и возвращает корректный JSON, однако внутри базы 1С метод ПолучитьТелоКакСтроку() выдает пустую строку. Разберем по шагам, почему так происходит, какие скрытые нюансы есть в объектах платформы HTTPСоединение и HTTPЗапрос, и как правильно построить обращение к REST API.

Причина 1. Неверное указание адреса ресурса в HTTPЗапрос

Самая распространенная ошибка при работе со стандартными механизмами платформы — передача полного URL-адреса вместе с протоколом и именем хоста в конструктор HTTPЗапрос. Проанализируем исходный код автора:


URL = "http://api.weatherapi.com/v1/history.json?" + "key=" + API_key + "&q=" + ШиротаДолгота + "&dt=" + ДатаЗапрос;
Запрос = Новый HTTPЗапрос(URL);
Соединение = Новый HTTPСоединение("api.weatherapi.com");

В объекте HTTPСоединение в качестве первого параметра уже задается адрес целевого сервера — api.weatherapi.com. Конструктор объекта HTTPЗапрос ожидает не абсолютный URL, а относительный путь к ресурсу на этом сервере (включая параметры строки запроса). Когда мы передаем в HTTPЗапрос полный адрес с протоколом и хостом, сервер получает искаженный заголовок запроса и не может обработать его корректно.

Посмотрим на правильное формирование пути:


// Указываем только относительный путь к эндпоинту
ОтносительныйURL = "/v1/history.json?key=" + API_key + "&q=" + ШиротаДолгота + "&dt=" + ДатаЗапрос;
Запрос = Новый HTTPЗапрос(ОтносительныйURL);

Причина 2. Редиректы с HTTP на HTTPS и отсутствие защищенного соединения

Вторая распространенная проблема заключается в использовании протокола http://. Практически все современные погодные и картографические сервисы в целях безопасности принудительно перенаправляют незащищенный трафик на безопасный протокол https://, возвращая коды состояния 301 Moved Permanently или 302 Found.

Браузер переходит по таким перенаправлениям автоматически и незаметно для пользователя. Однако объект платформы HTTPСоединение не переходит по редиректам самостоятельно. В итоге 1С получает пустой ответ с кодом 301, а вызов Ответ.ПолучитьТелоКакСтроку() возвращает пустоту.

Для исправления ситуации необходимо сразу подключаться через защищенный порт 443 с инициализацией объекта ЗащищенноеСоединениеOpenSSL:


Защита = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение("api.weatherapi.com", 443, , , , , Защита);

Причина 3. Блокировка запросов без заголовка User-Agent

Многие облачные сервисы и системы защиты (такие как Cloudflare) отсекают запросы от автоматических систем, если в заголовках отсутствует понятный идентификатор клиента. Если заголовок User-Agent не задан или содержит стандартную системную сигнатуру 1С, сервис может вернуть ошибку 403 Forbidden.

Добавим стандартный заголовок браузера в наш запрос:


Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

Итоговый пример надежного получения данных

Объединим все исправления в единую процедуру. Обязательно добавим анализ свойства КодСостояния у объекта ответа и явное указание кодировки КодировкаТекста.UTF8:


&НаСервере
Процедура ПолучитьПогодуНаСервере(ДатаЗапрос, API_key)
    
    ШиротаДолгота = "59.9386,30.3141";
    
    // 1. Формируем только относительный путь с параметрами
    ОтносительныйURL = "/v1/history.json?key=" + API_key 
        + "&q=" + ШиротаДолгота 
        + "&dt=" + ДатаЗапрос;
    
    Запрос = Новый HTTPЗапрос(ОтносительныйURL);
    Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
    
    // 2. Инициализируем защищенное HTTPS-соединение
    Защита = Новый ЗащищенноеСоединениеOpenSSL();
    Соединение = Новый HTTPСоединение("api.weatherapi.com", 443, , , , 30, Защита);
    
    Попытка
        Ответ = Соединение.Получить(Запрос);
        
        // 3. Всегда проверяем код состояния ответа
        Если Ответ.КодСостояния = 200 Тогда
            ТекстJSON = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
            Сообщить(ТекстJSON);
        Иначе
            Сообщить("Ошибка запроса. Код состояния: " + Ответ.КодСостояния);
            Сообщить(Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8));
        КонецЕсли;
    Исключение
        Сообщить("Не удалось выполнить запрос: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Чек-лист для диагностики проблем с HTTP-запросами

Если после корректировки кода данные все равно не приходят, разберем возможные сетевые ограничения:

  1. Разница контекстов выполнения: Процедура исполняется на стороне сервера (директива &НаСервере). Если на компьютере разработчика браузер имеет прямой выход в интернет, то на сервере 1С сетевой доступ к внешним ресурсам может быть ограничен системным администратором или брандмауэром.
  2. Работа через прокси: Если в локальной сети выход во внешнюю сеть осуществляется через корпоративный шлюз, необходимо передавать настроенный объект ПроксиСервер в конструктор HTTPСоединение.
  3. Альтернативное решение для Windows: Если требуется прозрачная обработка всех редиректов и SSL-сертификатов на уровне операционной системы, можно использовать COM-объект WinHttp.WinHttpRequest.5.1, который ведет себя аналогично браузеру.
← На главную