Работа с внешними API в 1С — это стандартная задача, но она часто сопровождается трудноуловимыми ошибками. Одна из самых коварных проблем — визуальное или фактическое «обрезание» текста запроса или ответа. В этой статье мы подробно разберем, почему данные могут пропадать, как на это влияют кодировки и какие инструменты помогут найти «потерянные» байты.
Проанализируем фрагмент кода, который часто становится источником бед. Рассмотрим ситуацию: программист устанавливает тело запроса, используя кодировку windows-1251 и принудительно включает использование BOM. Это критическая ошибка при работе с современными веб-сервисами.
Byte Order Mark (BOM) — это специальная последовательность байтов в начале текстового файла или потока. Она предназначена для определения порядка байтов в кодировках семейства UTF. Для кодировки windows-1251 (ANSI) стандарт BOM вообще не предусмотрен. Когда мы заставляем 1С вставить BOM в поток windows-1251, в начале сообщения появляются лишние «мусорные» байты. Веб-сервер, ожидающий чистый JSON, видит эти символы перед открывающей скобкой { и может либо оборвать соединение, либо некорректно интерпретировать длину сообщения.
Выясним причину, почему стоит избегать такого подхода, и перейдем к правильному методу установки тела запроса:
// Неправильно:
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, "windows-1251", ИспользованиеByteOrderMark.Использовать);
// Правильно (золотой стандарт для JSON):
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
Часто кажется, что данные обрезаются при получении ответа. Проанализируем ситуацию: вы вызываете HTTPОтвет.ПолучитьТелоКакСтроку(), и в переменной оказывается лишь часть ожидаемого текста. Рассмотрим три основные причины, почему так происходит:
HTTPОтвет данные физически присутствуют.windows-1251, интерпретатор может встретить последовательность байтов, не соответствующую целевой кодировке, и прекратить чтение.Для того чтобы исключить ошибки интерпретации строк, мы рекомендуем проверять объем полученных данных в «сыром» виде. Посмотрим на пример кода, который позволяет узнать реальный размер ответа:
ДвоичныеДанныеОтвета = HTTPОтвет.ПолучитьТелоКакДвоичныеДанные();
РазмерВБайтах = ДвоичныеДанныеОтвета.Размер();
Сообщить("Получено байт: " + РазмерВБайтах);
// Теперь читаем данные правильно, зная, что сервер обычно присылает UTF-8
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьДвоичныеДанные(ДвоичныеДанныеОтвета, "UTF-8");
Результат = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Использование метода УстановитьДвоичныеДанные у объекта ЧтениеJSON гораздо надежнее, чем предварительное преобразование в промежуточную строку 1С.
Рассмотрим вопрос управления длиной контента. В норме 1С автоматически вычисляет заголовок Content-Length при использовании метода УстановитьТелоИзСтроки. Однако если вы формируете заголовки вручную, убедитесь, что вы не передаете туда фиксированное значение, которое меньше реального размера строки. Помните: Content-Length — это количество байтов, а не количество символов. В UTF-8 один кириллический символ занимает 2 байта, поэтому расчет длины через функцию СтрДлина() будет ошибочным.
Если программные методы не помогают, проанализируем ситуацию на уровне сетевых пакетов. Существует класс программ, называемых HTTP-дебаггерами (например, Fiddler или Charles). Они работают как прокси-сервер и позволяют увидеть, что именно уходит из 1С «на лету».
Выясним, как ими пользоваться для решения нашей проблемы:
HTTPСоединение укажите параметры прокси-сервера 127.0.0.1 и соответствующий порт).Подводя итог, проанализируем лучшие практики для предотвращения «обрезания» данных в 1С:
ЗаписьJSON. Это гарантирует валидность структуры.ПолучитьТелоКакДвоичныеДанные).Соблюдение этих правил позволит сделать ваши интеграции надежными и избавит от загадочных ошибок с «пропадающими» данными.