Разработка и Конфигурация · 13 мин
Как разобрать HTTP-ответ в 1С: разбор кода, заголовков и тела ответа
Практическое руководство по разбору HTTP-ответа в 1С: чтение кода состояния, заголовков, тела ответа, парсинг JSON и обработка ошибок с примерами кода.
При обмене данными с внешними сервисами — банками, маркетплейсами, курьерскими службами, внутренними API — разработчик 1С получает HTTP-ответ и должен корректно его интерпретировать: понять, успешен ли запрос, что вернул сервер и как извлечь нужные данные. Ошибка на этом этапе приводит либо к падению обработки, либо к тихой потере данных, что гораздо опаснее.
Объект HTTPОтвет в платформе 1С содержит три ключевые части: код состояния (число вроде 200, 404, 500), коллекцию заголовков и тело ответа — строку, поток или двоичные данные. Каждая часть разбирается своими методами, и у каждой есть типичные подводные камни: кодировки, перенаправления, сжатие, нестандартные ответы сервера.
Ниже разобран полный цикл работы с ответом: от выполнения запроса до проверки результата и обработки ошибок, с примерами кода, которые можно переносить в свои обработки практически без изменений.
Как выполнить запрос и получить объект ответа
Разбор начинается с корректного выполнения запроса. Создаётся соединение HTTPСоединение, формируется HTTPЗапрос с указанием ресурса и заголовков, затем вызывается один из методов: Получить() (GET), ОтправитьДляОбработки() (POST), Записать() (PUT) или Удалить() (DELETE).
Типовой каркас выглядит так:
Соединение = Новый HTTPСоединение("api.example.ru", 443, , , , 30,
Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/v1/orders?date=2026-01-01");
Запрос.Заголовки.Вставить("Accept", "application/json");
Запрос.Заголовки.Вставить("Authorization", "Bearer " + Токен);
Ответ = Соединение.Получить(Запрос);
Обратите внимание на таймаут (в примере — 30 секунд). Без него при недоступном сервере фоновое задание или сеанс пользователя зависнет надолго. Для интерактивных операций разумно ставить таймаут меньше, для обмена большими файлами — больше.
Результат вызова — объект HTTPОтвет, с которым и идёт дальнейшая работа. Важно: сам вызов метода не бросает исключение при кодах 4xx и 5xx — сервер ответил, и платформа считает обмен успешным. Проверка кода состояния — обязанность разработчика.
Как проверить код состояния ответа
Свойство КодСостояния возвращает целое число. Первое, что нужно сделать после получения ответа, — классифицировать этот код, а не сразу лезть в тело.
| Диапазон | Значение | Действие в 1С |
|---|---|---|
| 200–299 | Успех: 200 OK, 201 Created, 204 No Content | Разбирать тело (для 204 тела может не быть) |
| 301, 302, 307 | Перенаправление | Проверить заголовок Location, повторить запрос по новому адресу |
| 400, 422 | Ошибка в данных запроса | Разобрать тело — сервер часто пишет причину |
| 401, 403 | Нет авторизации или прав | Проверить токен, ключ, срок его действия |
| 404 | Ресурс не найден | Проверить URL и параметры |
| 429 | Превышен лимит запросов | Подождать и повторить с паузой |
| 500–599 | Ошибка на стороне сервера | Повторить позже, залогировать тело ответа |
Пример проверки:
Если Ответ.КодСостояния >= 200 И Ответ.КодСостояния < 300 Тогда
// разбор тела
ИначеЕсли Ответ.КодСостояния = 401 Тогда
ВызватьИсключение "Ошибка авторизации: проверьте токен доступа";
Иначе
ВызватьИсключение СтрШаблон("Сервер вернул код %1: %2",
Ответ.КодСостояния,
Лев(Ответ.ПолучитьТелоКакСтроку(), 500));
КонецЕсли;
Как прочитать и разобрать заголовки ответа
Заголовки хранятся в свойстве Заголовки — это соответствие, где ключи регистронезависимы. Чаще всего из заголовков нужны тип содержимого, кодировка и служебные поля вроде Location или Retry-After.
ТипСодержимого = Ответ.Заголовки.Получить("Content-Type");
// например: "application/json; charset=utf-8"
Если ТипСодержимого <> Неопределено
И СтрНайти(НРег(ТипСодержимого), "application/json") > 0 Тогда
// безопасно разбирать как JSON
КонецЕсли;
Проверка Content-Type перед разбором тела — хорошая практика. Если сервер вместо JSON вернул HTML-страницу ошибки (так делают прокси и балансировщики при сбоях), попытка прочитать её как JSON выдаст невразумительное исключение. Предварительная проверка типа позволяет сразу выдать понятное сообщение.
Отдельный случай — перенаправления. Платформа 1С не всегда автоматически следует редиректам, поэтому при кодах 301/302/307 нужно самостоятельно взять заголовок Location и выполнить новый запрос. Следите, чтобы цикл перенаправлений не был бесконечным — ограничьте число переходов, например, пятью.
Как получить тело ответа: строка, поток, двоичные данные
Платформа предлагает три метода чтения тела, и выбор зависит от характера данных:
ПолучитьТелоКакСтроку()— для текстовых ответов: JSON, XML, HTML, CSV. Метод сам определяет кодировку по заголовку Content-Type, при необходимости кодировку можно передать параметром.ПолучитьТелоКакДвоичныеДанные()— для файлов: картинок, PDF, архивов. Дальше данные записываются черезЗаписать()в файл или помещаются во временное хранилище.ПолучитьТелоКакПоток()— для больших ответов, когда нежелательно загружать всё в память. Поток можно построчно читать или перенаправить в файл.
Для больших файлов есть более удобная альтернатива: метод соединения Получить(Запрос, ИмяФайлаРезультата) сразу пишет тело в файл на диске, минуя память сервера 1С. Это заметно снижает риск нехватки памяти при скачивании отчётов и выгрузок объёмом в сотни мегабайт.
Частая проблема со строковым чтением — «кракозябры» вместо кириллицы. Причина почти всегда в том, что сервер не указал кодировку в заголовке, а платформа приняла тело за Latin-1. Решение — явно передать кодировку: Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8).
Как выбрать способ чтения тела
Как разобрать JSON из тела ответа
Большинство современных API возвращают JSON. В 1С для разбора используется объект ЧтениеJSON в связке с ПрочитатьJSON:
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ТекстОтвета);
Данные = ПрочитатьJSON(Чтение); // Соответствие или Массив
Чтение.Закрыть();
Для Каждого Заказ Из Данные["orders"] Цикл
НомерЗаказа = Заказ["number"];
Сумма = Заказ["total"];
КонецЦикла;
По умолчанию ПрочитатьJSON возвращает Соответствие. Если нужны привычные обращения через точку (Данные.orders вместо Данные["orders"]), передайте вторым параметром Истина — тогда результат будет структурой. Но помните: имена ключей JSON с дефисами или начинающиеся с цифры в структуру не преобразуются корректно.
Даты в JSON приходят строками. Их можно преобразовать автоматически, указав в ПрочитатьJSON параметр с именами полей дат и форматом ФорматДатыJSON.ISO, либо разбирать вручную через ПрочитатьДатуJSON(). Ручной вариант надёжнее, когда сервер присылает даты в нестандартном виде.
Всегда проверяйте существование ключей перед обращением: Если Данные.Получить("orders") <> Неопределено Тогда .... Структура ответа внешнего API может меняться без предупреждения, и обращение к отсутствующему ключу у соответствия вернёт Неопределено, а у структуры — вызовет исключение.
Функция РазобратьОтветJSON(Ответ)
Если Ответ.КодСостояния < 200 ИЛИ Ответ.КодСостояния >= 300 Тогда
ВызватьИсключение СтрШаблон("HTTP %1", Ответ.КодСостояния);
КонецЕсли;
Текст = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Текст);
Результат = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
Возврат Результат;
КонецФункцииКак обработать ошибки и нестандартные ситуации
Помимо кодов ошибок сервера, встречаются сбои на уровне соединения: таймаут, разрыв SSL, недоступность хоста. Такие ситуации вызывают исключение платформы ещё на этапе вызова метода, поэтому весь обмен стоит оборачивать в Попытка ... Исключение ... КонецПопытки с записью подробностей в журнал регистрации.
Попытка
Ответ = Соединение.Получить(Запрос);
Исключение
ЗаписьЖурналаРегистрации("Обмен с API",
УровеньЖурналаРегистрации.Ошибка, , ,
ОписаниеОшибки());
ВызватьИсключение "Сервис недоступен, попробуйте позже";
КонецПопытки;
Ещё одна нестандартная ситуация — пустое тело при успешном коде. Код 204 No Content штатно означает отсутствие тела, и попытка прочитать из него JSON закончится ошибкой. Проверяйте длину строки перед разбором.
Некоторые серверы сжимают ответы gzip. Если в запросе вы сами не ставили заголовок Accept-Encoding: gzip, сервер обычно отвечает несжатым текстом. Если сжатие всё же используется, тело нужно распаковать — например, через объекты работы с zip-потоками или отказавшись от запроса сжатия.
Как проверить результат и залогировать обмен
После разбора ответа полезно убедиться, что данные сошлись: количество загруженных записей соответствует ожиданию, обязательные поля заполнены, суммы и даты в разумных пределах. Для отладки обменов держите в конфигурации механизм логирования: сохраняйте URL запроса, код ответа и первые несколько сотен символов тела.
При отладке удобно выводить ответ целиком во временный файл и открывать его в текстовом редакторе с подсветкой JSON — так структура видна нагляднее, чем в сообщении или журнале регистрации. Не оставляйте такой отладочный вывод в рабочем коде без ограничений: тела ответов могут содержать персональные данные и токены.
Как проверить результат
Значение в диапазоне 200–299
4xx или 5xx — запрос не выполнен, тело разбирать нельзя без анализа причины
Соответствует ожидаемому формату, например application/json
text/html при ожидании JSON — вероятно, ошибка прокси или неправильный URL
Валидный JSON, нужные ключи присутствуют
Пустая строка, кракозябры или HTML-страница ошибки
Количество и содержимое записей совпадает с данными в системе-источнике
Пропущены записи, даты или суммы сдвинуты — проверяйте формат и часовой пояс
Итоговая логика устойчивого обмена проста: выполнили запрос с таймаутом → проверили код состояния → проверили тип содержимого → прочитали тело подходящим методом → разобрали с проверкой ключей → залогировали результат. Такая последовательность переживает большинство сбоев внешних сервисов без потери данных.
Что важно запомнить
Разбор HTTP-ответа в 1С строится вокруг трёх шагов: проверка КодСостояния, чтение Заголовков и извлечение тела подходящим методом. JSON разбирается через ЧтениеJSON и ПрочитатьJSON с обязательной проверкой существования ключей. Таймаут соединения, обработка исключений и логирование — обязательный минимум для производственного обмена.
Частые вопросы
Чем отличается ПолучитьТелоКакСтроку() от ПолучитьТелоКакДвоичныеДанные()?
Первый метод интерпретирует тело как текст с учётом кодировки и подходит для JSON, XML, HTML. Второй возвращает сырые байты и нужен для файлов — изображений, PDF, архивов. Если прочитать бинарный файл как строку, данные будут безвозвратно испорчены при перекодировании.
Почему ПрочитатьJSON выдаёт ошибку, хотя сервер ответил успешно?
Чаще всего причины три: тело пустое (код 204), сервер вернул не JSON, а HTML-страницу или текст ошибки, либо в начале строки стоит BOM или лишние символы. Выведите первые 200–300 символов тела в журнал — причина обычно видна сразу.
Как автоматически преобразовать даты из JSON?
Передайте в ПрочитатьJSON параметры: имена полей с датами (строкой через запятую или массивом) и формат ФорматДатыJSON.ISO. Тогда указанные поля сразу станут значениями типа Дата. Поля, не попавшие в список, останутся строками и потребуют ручного разбора.
Сервер возвращает 401, хотя токен правильный. Что проверить?
Убедитесь, что токен передаётся именно в том заголовке и формате, который ждёт API (например, «Bearer » с пробелом перед токеном), что токен не истёк и что в запросе нет лишних пробелов или переводов строк. Также проверьте, не перехватывает ли запрос прокси, требующий собственной авторизации.
Как скачать большой файл, не загружая его в память?
Передайте вторым параметром метода Получить() путь к файлу на диске: Соединение.Получить(Запрос, "C:\Temp\report.zip"). Платформа запишет тело напрямую в файл. После скачивания проверьте код состояния — файл создаётся даже при ошибочном ответе, и в нём может оказаться текст ошибки вместо данных.
Нужно ли закрывать HTTPСоединение после запроса?
Явного метода закрытия у HTTPСоединения нет — соединение освобождается при уничтожении объекта. Однако если выполняется много запросов подряд к одному серверу, выгоднее создать соединение один раз и переиспользовать его, чем открывать заново на каждый запрос.