При интеграции 1С с внешними системами часто возникает необходимость получить данные в формате JSON по HTTP или HTTPS-ссылке. Однако, при работе с защищенным протоколом HTTPS, можно столкнуться с распространенной ошибкой "400 Bad Request", которая указывает на неверную настройку соединения. В этой статье мы подробно разберем, как правильно настроить HTTP-запрос в 1С для работы с HTTPS, обработать полученные JSON-данные и вывести их в таблицу значений на форме, а также рассмотрим типичные ошибки и способы их устранения.
Предположим, мы хотим получить структуру JSON с внешнего сервера по HTTPS-ссылке, например, https://apps-2.v.ru/test_1c.php. Начальный подход может выглядеть так:
&НаКлиенте
Процедура Загрузить(Команда)
ВыполнитьЗагрузкуНаСервере();
КонецПроцедуры
// Внимание: для работы с HTTPСоединение в тонком/веб-клиенте требуется &НаСервере
// В данном примере, для упрощения, код пока находится на клиенте, но рекомендуется переносить на сервер.
// &НаКлиенте или &НаСервере, в зависимости от контекста приложения
Процедура ВыполнитьЗагрузкуНаСервере()
HTTPСоединение = Новый HTTPСоединение("https://apps-2.v.ru ,); // Обратите внимание на лишнюю запятую и отсутствие порта
HTTPЗапрос = Новый HTTPЗапрос("/test_1c.php");
HTTPЗапрос.Заголовки.Вставить("Content-type", "application/json");
Запрос = HTTPСоединение.Получить(HTTPЗапрос); // Здесь возникает ошибка
Результат = ЧтениеJSON(Запрос.ПолучитьТелоКакСтроку());
КонецПроцедуры
При попытке выполнить такой запрос, мы можем получить ошибку на строке Запрос = HTTPСоединение.Получить(HTTPЗапрос);. После корректировки синтаксиса (убрав лишнюю запятую в конструкторе HTTPСоединение), следующей распространенной ошибкой будет "400 Bad Request" (Ошибочный запрос) с подробным описанием:
400 Bad Request
Bad Request
Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.
А затем, если мы пытаемся прочитать этот HTML-текст как JSON, получаем ошибку: "Непредвиденный символ при чтении JSON".
Что означает эта ошибка? Сообщение "You're speaking plain HTTP to an an SSL-enabled server port. Instead use the HTTPS scheme to access this URL, please." (Вы обращаетесь по обычному HTTP к порту сервера с поддержкой SSL. Вместо этого используйте схему HTTPS для доступа к этому URL, пожалуйста.) прямо указывает на причину: мы пытаемся установить незащищенное HTTP-соединение с сервером, который ожидает защищенное HTTPS-соединение. Даже если в строке мы указали "https://", объект HTTPСоединение по умолчанию не использует SSL/TLS шифрование, если ему явно не указать это.
Вторая ошибка "Непредвиденный символ при чтении JSON" возникает потому, что вместо ожидаемого JSON-ответа сервер прислал нам HTML-страницу с описанием ошибки "400 Bad Request". Функция ЧтениеJSON(), естественно, не может разобрать HTML как JSON.
Для корректной работы с HTTPS-запросами в 1С необходимо использовать объект ЗащищенноеСоединениеOpenSSL. Этот объект является обязательным параметром в конструкторе HTTPСоединение, когда мы взаимодействуем с серверами по протоколу HTTPS.
Разберем параметры конструктора HTTPСоединение и ЗащищенноеСоединениеOpenSSL подробнее:
Новый HTTPСоединение(ИмяСервера, Порт, Пользователь, Пароль, Таймаут, ФлагЗаписиПротокола, ЗащищенноеСоединение, ДополнительныеЗаголовки)
ИмяСервера: Имя или IP-адрес сервера (например, "apps-2.v.ru"). Важно: не включайте "https://" сюда. Это указывается через параметр ЗащищенноеСоединение.Порт: Для HTTPS это обычно 443.Пользователь, Пароль: Если требуется HTTP-аутентификация (Basic или Digest). В данном случае, судя по примеру, это "admin" и "1234".Таймаут: Время ожидания ответа от сервера в секундах. По умолчанию может быть небольшим, для медленных серверов рекомендуется увеличить.ЗащищенноеСоединение: Вот здесь мы и передаем объект ЗащищенноеСоединениеOpenSSL().Новый ЗащищенноеСоединениеOpenSSL(СертификатКлиента, ПарольСертификата, ПутьККорневымСертификатам, ПроверятьСервер)
СертификатКлиента: Объект СертификатМенеджер, если сервер требует клиентский сертификат для аутентификации. В большинстве случаев не используется.ПарольСертификата: Пароль к клиентскому сертификату.ПутьККорневымСертификатам: Путь к файлу или каталогу, содержащему корневые сертификаты, если сервер использует самоподписанные или корпоративные сертификаты, не доверенные ОС. В большинстве случаев, если сервер использует стандартные доверенные сертификаты, этот параметр можно не указывать, и 1С будет использовать системное хранилище.ПроверятьСервер: Логическое значение. Истина (по умолчанию) - 1С будет проверять подлинность сертификата сервера. Ложь - проверка отключается (не рекомендуется для продуктивных систем из соображений безопасности).Для большинства стандартных случаев, когда сервер использует доверенные SSL-сертификаты, достаточно создать ЗащищенноеСоединениеOpenSSL без параметров:
Новый ЗащищенноеСоединениеOpenSSL()
Теперь, когда мы понимаем, как правильно настроить защищенное соединение, давайте применим эти знания и перепишем наш код. Для лучшей практики, операции с внешними HTTP-запросами рекомендуется выполнять на сервере, так как это обеспечивает лучшую безопасность и управляемость, особенно в веб- и тонком клиенте.
Сначала определим процедуру на клиенте, которая будет вызывать серверную процедуру для выполнения запроса:
&НаКлиенте
Процедура Загрузить(Команда)
ЭтотОбъект.тзДанныеJSON.Очистить(); // Очищаем таблицу значений перед загрузкой
ВыполнитьЗагрузкуНаСервере();
КонецПроцедуры
Далее, создаем серверную процедуру ВыполнитьЗагрузкуНаСервере(). Здесь мы правильно инициализируем HTTPСоединение с использованием ЗащищенноеСоединениеOpenSSL.
&НаСервере
Процедура ВыполнитьЗагрузкуНаСервере()
Попытка
// Имя сервера, порт 443 для HTTPS, пользователь и пароль для аутентификации
// Использование ЗащищенноеСоединениеOpenSSL для защищенного соединения
HTTPСоединение = Новый HTTPСоединение("apps-2.v.ru", 443, "admin", "1234",,, Новый ЗащищенноеСоединениеOpenSSL());
HTTPЗапрос = Новый HTTPЗапрос("/test_1c.php");
HTTPЗапрос.Заголовки.Вставить("Content-type", "application/json");
// Если ожидаем ответ в определенной кодировке, можно указать (например, "UTF-8")
// HTTPЗапрос.Заголовки.Вставить("Accept-Charset", "UTF-8");
HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
Если HTTPОтвет.Статус = 200 Тогда // Проверяем успешность выполнения запроса
// Получаем тело ответа как строку
СтрокаJSON = HTTPОтвет.ПолучитьТелоКакСтроку();
// Вызываем функцию для чтения и парсинга JSON
ЧтениеJSONВТаблицу(СтрокаJSON);
Иначе
СообщениеОбОшибке = "Ошибка HTTP-запроса. Статус: " + HTTPОтвет.Статус + ". Тело ответа: " + HTTPОтвет.ПолучитьТелоКакСтроку();
Сообщить(СообщениеОбОшибке);
ЖурналРегистрации.Записать(
"ОшибкаHTTPЗапроса",
УровеньЖурнала.Ошибка,
,
,
СообщениеОбОшибке
);
КонецЕсли;
Исключение
Сообщить("Произошла ошибка при выполнении HTTP-запроса: " + ОписаниеОшибки());
ЖурналРегистрации.Записать(
"ОшибкаHTTPСоединения",
УровеньЖурнала.Ошибка,
,
,
"Не удалось выполнить HTTP-запрос: " + ОписаниеОшибки()
);
КонецПопытки;
КонецПроцедуры
Обратите внимание на несколько ключевых моментов в этом коде:
Попытка...Исключение для корректной обработки возможных сетевых ошибок или ошибок таймаута.HTTPОтвет.Статус. Статус 200 означает успешное выполнение запроса. Если статус другой (например, 404, 500, или в нашем случае 400), это указывает на проблему на стороне сервера или запроса. Только после проверки статуса мы приступаем к обработке тела ответа.HTTPСоединение создается с указанием имени сервера, порта (443), аутентификационных данных и объекта Новый ЗащищенноеСоединениеOpenSSL().Получить объекта HTTPСоединение возвращает объект HTTPОтвет, из которого мы можем получить статус и тело ответа.После успешного получения строки JSON, нам необходимо ее прочитать и заполнить таблицу значений на форме. Для этого мы создадим отдельную функцию ЧтениеJSONВТаблицу.
&НаСервере
// Функция, которая будет вызываться с сервера для чтения JSON и заполнения таблицы значений на форме
Функция ЧтениеJSONВТаблицу(ДанныеJSON)
ЧтениеJSONОбъект = Новый ЧтениеJSON;
ЧтениеJSONОбъект.УстановитьСтроку(ДанныеJSON);
// ПрочитатьJSON автоматически десериализует JSON в структуру или массив 1С
СтруктураДанных = ПрочитатьJSON(ЧтениеJSONОбъект, Истина); // Истина - для использования совместимости с JSON RFC 4627
// Проверяем, соответствует ли структура JSON нашим ожиданиям
Если СтруктураДанных.Свойство("Products") И ТипЗнч(СтруктураДанных.Products) = Тип("Массив") Тогда
Для Каждого ЭлементСтруктуры Из СтруктураДанных.Products Цикл
// Создаем новую строку в таблице значений на форме
НоваяСтрока = ЭтотОбъект.тзДанныеJSON.Добавить();
// Заполняем поля новой строки
НоваяСтрока.id = ЭлементСтруктуры.id;
НоваяСтрока.name = ЭлементСтруктуры.name;
НоваяСтрока.price = ЭлементСтруктуры.price;
НоваяСтрока.stock = ЭлементСтруктуры.stock;
КонецЦикла;
Иначе
Сообщить("Структура JSON не содержит ожидаемого массива 'Products' или имеет неверный формат.");
ЖурналРегистрации.Записать(
"ОшибкаПарсингаJSON",
УровеньЖурнала.Ошибка,
,
,
"Неверная структура JSON: " + ДанныеJSON
);
КонецЕсли;
ЧтениеJSONОбъект.Закрыть();
Возврат Истина;
Исключение
Сообщить("Произошла ошибка при чтении JSON: " + ОписаниеОшибки());
ЖурналРегистрации.Записать(
"ОшибкаПарсингаJSON",
УровеньЖурнала.Ошибка,
,
,
"Не удалось прочитать JSON: " + ОписаниеОшибки() + " Данные: " + ДанныеJSON
);
Возврат Ложь;
КонецФункции
В этой функции мы используем стандартные объекты 1С для работы с JSON:
Новый ЧтениеJSON; – создает объект для чтения JSON.ЧтениеJSON.УстановитьСтроку(ДанныеJSON); – указывает, какую строку JSON следует читать.ПрочитатьJSON(ЧтениеJSON,,,,, ЭтотОбъект); – эта функция автоматически десериализует JSON в структуры и массивы 1С. Важно, чтобы JSON-строка была корректной. Второй параметр Истина при вызове ПрочитатьJSON указывает на использование совместимости с JSON RFC 4627, что полезно для более строгого соответствия стандарту.Структура.Products, чтобы получить массив данных. Затем в цикле обходим этот массив и добавляем данные в строки таблицы значений формы (ЭтотОбъект.тзДанныеJSON).Попытка...Исключение для обработки возможных ошибок парсинга JSON, таких как "Непредвиденный символ при чтении JSON", если по какой-то причине полученная строка не является валидным JSON.Для корректного вывода данных на форму, не забудьте, что таблица значений тзДанныеJSON должна быть определена как реквизит формы с соответствующими колонками (id, name, price, stock) и связана с элементом управления "Таблица" на форме.
Даже с правильной настройкой HTTPS, могут возникнуть другие проблемы. Рассмотрим, как их предотвратить и обработать:
Статус объекта HTTPОтвет.
200 OK: Запрос успешно выполнен.400 Bad Request: Некорректный запрос с нашей стороны (например, неверные параметры, заголовки).401 Unauthorized: Требуется аутентификация или она не пройдена.403 Forbidden: Доступ запрещен.404 Not Found: Ресурс не найден по указанному URL.500 Internal Server Error: Ошибка на стороне сервера.Content-type: application/json обычно подразумевает UTF-8, сервер может вернуть данные в другой кодировке. В таких случаях можно попробовать явно указать кодировку при получении тела ответа, если это поддерживается, или выполнить перекодировку строки. Однако, в большинстве современных систем JSON передается в UTF-8.HTTPСоединение можно явно указать таймаут в секундах, например: Новый HTTPСоединение("apps-2.v.ru", 443, "admin", "1234", 30, , Новый ЗащищенноеСоединениеOpenSSL()); (30 секунд).HTTPСоединение или через глобальные настройки интернет-соединения в 1С.ПрочитатьJSON() является оптимальным и простым способом. Однако, для очень больших JSON-файлов, которые могут потреблять много памяти при полной десериализации, ЧтениеJSON предоставляет возможность потокового чтения. Это требует более сложной логики ручного парсинга, но может быть эффективнее для крайне больших объемов данных. В нашем случае, для получения структуры и вывода в таблицу значений, стандартный подход через ПрочитатьJSON() вполне подходит.Как мы видим, успешное получение JSON-данных по HTTPS-ссылке в 1С сводится к правильной настройке объекта HTTPСоединение с обязательным использованием ЗащищенноеСоединениеOpenSSL. Кроме того, критически важна надежная обработка ошибок: проверка статуса HTTP-ответа и использование блоков Попытка...Исключение. Стандартные функции ЧтениеJSON и ПрочитатьJSON значительно упрощают десериализацию данных в структуры, удобные для работы в 1С. Следуя этим рекомендациям, мы сможем эффективно интегрировать 1С с внешними системами, получая и обрабатывая необходимые данные.