При интеграции 1С с внешними веб-сервисами разработчики нередко сталкиваются с ситуацией: сформированный URL прекрасно открывается в интернет-браузере и возвращает корректный JSON, однако внутри базы 1С метод ПолучитьТелоКакСтроку() выдает пустую строку. Разберем по шагам, почему так происходит, какие скрытые нюансы есть в объектах платформы HTTPСоединение и HTTPЗапрос, и как правильно построить обращение к REST API.
Самая распространенная ошибка при работе со стандартными механизмами платформы — передача полного 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);
Вторая распространенная проблема заключается в использовании протокола http://. Практически все современные погодные и картографические сервисы в целях безопасности принудительно перенаправляют незащищенный трафик на безопасный протокол https://, возвращая коды состояния 301 Moved Permanently или 302 Found.
Браузер переходит по таким перенаправлениям автоматически и незаметно для пользователя. Однако объект платформы HTTPСоединение не переходит по редиректам самостоятельно. В итоге 1С получает пустой ответ с кодом 301, а вызов Ответ.ПолучитьТелоКакСтроку() возвращает пустоту.
Для исправления ситуации необходимо сразу подключаться через защищенный порт 443 с инициализацией объекта ЗащищенноеСоединениеOpenSSL:
Защита = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение("api.weatherapi.com", 443, , , , , Защита);
Многие облачные сервисы и системы защиты (такие как 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));
КонецЕсли;
Исключение
Сообщить("Не удалось выполнить запрос: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Если после корректировки кода данные все равно не приходят, разберем возможные сетевые ограничения:
&НаСервере). Если на компьютере разработчика браузер имеет прямой выход в интернет, то на сервере 1С сетевой доступ к внешним ресурсам может быть ограничен системным администратором или брандмауэром.ПроксиСервер в конструктор HTTPСоединение.WinHttp.WinHttpRequest.5.1, который ведет себя аналогично браузеру.