Обновление технологической платформы «1С:Предприятие» — важный и регулярный процесс, необходимый для получения новых функций и исправлений безопасности. Однако иногда этот процесс приносит неожиданные «сюрпризы» разработчикам, особенно в механизмах интеграции. Одной из распространенных проблем, с которой мы сталкиваемся при переходе с версий 8.3.10–8.3.18 на современные релизы (8.3.21, 8.3.22 и выше), является внезапный отказ работы HTTP-запросов, которые годами функционировали исправно.
В этой статье мы подробно разберем ситуацию, когда после обновления платформы перестают работать HTTPЗапрос с методами GET, и 1С возвращает ошибку "Ошибка работы с Интернет: Failure when receiving data from the peer". Мы проанализируем причины этого поведения, выясним, почему диагностика через Fiddler может вводить в заблуждение, и рассмотрим правильный подход к написанию кода интеграции, например, с использованием аутентификации по JWT-токену или валидатора OpenAPI-схем.
Рассмотрим типичный сценарий. У нас есть конфигурация (например, УПП или самописная база), которая обменивается данными с внешним API, например, для заполнения контрагентов по ИНН или создания счетов через POST-запросы. Код обмена прост и стабилен. После обновления платформы (например, с 8.3.11 до 8.3.22) исходящие запросы перестают выполняться.
При этом мы наблюдаем следующие странности:
Такое поведение часто ставит в тупик: кажется, что проблема «плавающая» или зависит от какой-то магии сети. Однако причина кроется в строгом следовании стандартам HTTP в новых версиях платформы.
Чтобы понять суть проблемы, нам нужно заглянуть «под капот» платформы 1С. Для реализации HTTP-соединений платформа использует популярную открытую библиотеку libcurl. В версиях платформы 8.3.21+ разработчики 1С обновили встроенную версию этой библиотеки, а также библиотек OpenSSL.
Более новые версии libcurl стали строже относиться к соблюдению спецификаций протокола HTTP (RFC 7231). Согласно стандартам, метод GET предназначен для получения данных и семантически не должен содержать тела запроса (Body). Хотя стандарт жестко не запрещает наличие тела, многие современные веб-серверы и промежуточные узлы считают GET-запрос с телом некорректным и разрывают соединение.
Ранее старые версии платформы (и старая libcurl) «прощали» разработчикам установку тела в GET-запросах, даже если это тело было пустой строкой. Теперь же механизмы работают иначе.
Давайте посмотрим на пример кода, который вызывал ошибку. Обратите внимание на создание и настройку объекта HTTPЗапрос.
// Создание соединения
Соединение = Новый HTTPСоединение(Выборка.Хост, , , , , , Новый ЗащищенноеСоединениеOpenSSL());
СтрокаЗапроса = Выборка.СтрокаЗапроса;
// ... логика подготовки строки ...
Запрос = Новый HTTPЗапрос(СтрокаЗапроса, Заголовки);
ТелоЗапроса = Выборка.ТелоЗапроса; // Часто здесь пустая строка для GET
// ... логика подготовки тела ...
// ВОТ ЗДЕСЬ КРОЕТСЯ ОШИБКА
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Выполнение запроса
Ответ = Соединение.ВызватьHTTPМетод(?(Выборка.МетодЗапроса = 0, "GET", "POST"), Запрос);
Разберем, что здесь происходит не так. Разработчик написал универсальный код, который обрабатывает и GET, и POST запросы. В переменной ТелоЗапроса для GET-запроса обычно содержится пустая строка "".
Метод УстановитьТелоИзСтроки выполняет следующие действия:
Content-Type и, что важнее, Content-Length).В новых версиях платформы вызов УстановитьТелоИзСтроки, даже с пустой строкой, сигнализирует библиотеке libcurl о том, что у запроса есть тело (пусть и нулевой длины). Это приводит к формированию пакета, который сервер воспринимает как ошибочный для метода GET, и соединение сбрасывается с ошибкой Failure when receiving data from the peer.
Этот момент часто сбивает с толку. Fiddler работает как Man-in-the-Middle (MITM) прокси. Схема работы выглядит так:
В процессе пересборки Fiddler часто «нормализует» запрос. Видя, что это GET-запрос и тело пустое, он может автоматически удалить лишние заголовки Content-Length или само тело, делая запрос валидным. Сервер получает корректный запрос от Fiddler и отвечает успешно. Это создает иллюзию, что проблема не в 1С, а в сети.
Для исправления ситуации мы должны гарантировать, что для метода GET мы вообще не трогаем тело запроса. Нам необходимо явно разделить логику подготовки запроса в зависимости от HTTP-метода.
Перепишем наш код, добавив проверку. Мы не должны вызывать методы установки тела (ни УстановитьТелоИзСтроки, ни УстановитьТелоИзДвоичныхДанных), если мы готовим GET-запрос.
Правильный алгоритм действий:
// Инициализация соединения и заголовков
Соединение = Новый HTTPСоединение(Хост, , , , , , Новый ЗащищенноеСоединениеOpenSSL());
Запрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
// Определяем метод запроса (например, "GET" или "POST")
МетодЗапроса = "GET"; // В реальном коде берем из параметров
// ВАЖНО: Устанавливаем тело только если это НЕ GET запрос
Если МетодЗапроса <> "GET" Тогда
// Подготовка тела нужна только для POST, PUT, PATCH
ТелоЗапроса = ПолучитьJSONТело();
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
КонецЕсли;
// Выполняем запрос
Попытка
Ответ = Соединение.ВызватьHTTPМетод(МетодЗапроса, Запрос);
Исключение
// Обработка ошибок соединения
ЗаписьЖурналаРегистрации("HTTPОшибка", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Таким образом, для GET-запроса объект HTTPЗапрос останется «чистым» в плане контента, библиотека libcurl не добавит лишних заголовков, и сервер корректно обработает обращение.
Раз уж мы обсуждаем проблемы сетевого обмена после обновления платформы, стоит упомянуть еще один важный нюанс, который часто возникает вместе с описанной выше проблемой.
Новые версии платформы (и обновленный OpenSSL внутри) по умолчанию отключают поддержку устаревших протоколов шифрования (SSLv3, TLS 1.0, TLS 1.1). Если API, к которому вы обращаетесь, находится на старом сервере, не поддерживающем TLS 1.2 или TLS 1.3, вы также получите ошибку соединения (часто Connection closed или ошибки SSL handshake).
Как это проверить и исправить:
cacert.pem, используемый платформой 1С.Если приведенное решение с телом запроса не помогло, или ошибка сохраняется, нам необходимо заглянуть глубже. Для этого используем Технологический журнал (ТЖ) 1С, который также можно экспортировать в Elastic для углубленного анализа.
Настроим сбор логов события NETWORK. Это позволит увидеть низкоуровневые ошибки библиотеки libcurl.
Пример настройки logcfg.xml для отлова сетевых ошибок:
<log location="C:\Logs\NetworkError" history="24">
<event>
<eq property="name" value="NETWORK"/>
</event>
<property name="all"/>
</log>
В полученных логах ищите свойства Descr или Error. Там могут быть указания на конкретные коды ошибок SSL (например, SEC_E_ALGORITHM_MISMATCH) или HTTP-протокола, которые точно укажут на причину разрыва соединения.
Обновление платформы — это шаг вперед к безопасности и стандартам, но он требует от нас пересмотра старого кода. Основные выводы для стабильной работы HTTP-запросов в современных версиях 1С:
УстановитьТелоИзСтроки для GET-запросов, даже с пустой строкой. Используйте условие Если.Применяя эти правила, вы сможете избежать простоев в интеграции и обеспечить стабильную работу обменов данными.