Как убрать принудительное кодирование в Base64 и исправить статус-код 206 на 200 в HTTP-сервисах 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке HTTP-сервисов на платформе 1С:Предприятие 8.3 программисты часто сталкиваются со специфическим поведением платформы и веб-серверов. Две самые распространенные проблемы при передаче текстовых данных на внешние устройства — это внезапное автоматическое кодирование текста в формат Base64 и подмена успешного статус-кода 200 OK на код 206 Partial Content. В этой статье мы подробно разберем природу этих явлений и рассмотрим надежные способы их устранения.

Часть 1: Почему 1С кодирует текстовый ответ в Base64 и как это предотвратить

Рассмотрим ситуацию: вам необходимо передать простой текстовый файл (например, список URL-адресов, конфигурационный файл или набор команд для микроконтроллера) на внешнее «умное» или «тупое» устройство. Вы используете стандартный метод УстановитьТелоИзСтроки() объекта HTTPСервисОтвет, но принимающая сторона вместо обычного текста получает строку в формате Base64.

Выясним причину этого поведения платформы:

Платформа 1С:Предприятие при отправке ответа через HTTPСервисОтвет пытается автоматически определить формат данных. Она делает это на основе анализа заголовка Content-Type и типа передаваемых данных. Логика платформы выглядит следующим образом:

  1. Если в заголовках ответа указан тип содержимого, который ассоциируется с бинарными данными (например, application/octet-stream, application/x-url или любой другой нестандартный подтип семейства application), 1С считает тело ответа двоичным.
  2. Если для установки тела такого «бинарного» ответа используется текстовый метод УстановитьТелоИзСтроки(), платформа принудительно кодирует строку в Base64. Это сделано для того, чтобы защитить потенциально бинарные данные от искажения спецсимволов при передаче по сети.
  3. Аналогичная ситуация происходит при использовании метода УстановитьИмяФайлаТела(): 1С определяет MIME-тип на основе расширения отправляемого файла. Если расширение не сопоставлено с текстовым типом, файл будет передан как Base64.

Давайте разберем два эффективных способа решения этой проблемы.

Способ 1.1: Использование правильного текстового MIME-типа

Самый простой способ избежать Base64-кодирования — явно указать платформе, что передаваемые данные являются текстом. Для этого нужно установить текстовый заголовок Content-Type. Вместо бинарных типов вроде application/x-url следует использовать стандартные текстовые MIME-типы:

Посмотрим на пример кода, где мы явно задаем текстовый формат в заголовках:


Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "text/plain; charset=utf-8");

ТекстОтвета = "строка1" + Символы.ПС + "строка2" + Символы.ПС + "строка3";
Ответ.УстановитьТелоИзСтроки(ТекстОтвета, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Возврат Ответ;

При использовании текстового MIME-типа платформа 1С передаст строку «как есть» в открытом виде без применения Base64.

Способ 1.2: Передача данных в бинарном виде напрямую

Что делать, если принимающее устройство жестко требует заголовок application/x-url или application/octet-stream, но при этом абсолютно не умеет декодировать Base64? В таком случае использование метода УстановитьТелоИзСтроки() нам не подходит.

Решением является самостоятельное преобразование строки в двоичные данные перед отправкой. Мы преобразуем текст в массив байтов в нужной кодировке и передаем его через метод УстановитьТелоИзДвоичныхДанных(). В этом случае 1С запишет байты в поток «как есть» и не будет пытаться применить Base64, независимо от того, какой Content-Type вы укажете.

Проанализируем пример реализации этого метода:


Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/x-url");

ТекстОтвета = "строка1" + Символы.ПС + "строка2";

// Преобразуем строку в двоичные данные. 
// Третий параметр "Ложь" отключает запись BOM (Byte Order Mark) в начало файла
ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(ТекстОтвета, КодировкаТекста.UTF8, Ложь);

Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные);

Возврат Ответ;

Этот подход гарантирует 100% контроль над отправляемыми байтами и позволяет обойти любые автоматические алгоритмы кодирования платформы 1С.

---

Часть 2: Почему возвращается статус 206 Partial Content вместо 200 OK

Теперь разберем вторую проблему: вы настроили HTTP-сервис, жестко указали в коде код состояния 200: Ответ = Новый HTTPСервисОтвет(200) или Ответ.КодСостояния = 200, но клиентское устройство все равно получает ответ со статусом 206 (Partial Content). При этом в заголовках ответа появляются параметры Content-Range.

Выясним причину этого странного поведения:

Важно понимать: платформа 1С сама по себе никогда принудительно не меняет код состояния 200 на 206. Подмена статуса происходит на уровне веб-сервера (IIS, Apache или Nginx), на котором опубликована информационная база 1С. Схема взаимодействия выглядит следующим образом:

  1. Клиентское устройство (особенно часто это микроконтроллеры, кассовые аппараты, терминалы сбора данных или кастомные утилиты скачивания) при отправке HTTP-запроса добавляет заголовок диапазона данных: например, Range: bytes=0- или Range: bytes=0-911. Клиент делает это для проверки поддержки дозагрузки файлов или скачивания данных частями.
  2. Веб-сервер принимает этот запрос и передает его в публикацию 1С.
  3. 1С успешно обрабатывает запрос, формирует полноценный ответ, устанавливает статус 200 OK и возвращает весь объем данных.
  4. Веб-сервер перехватывает ответ от 1С. Видя, что клиент изначально запрашивал только определенный диапазон (заголовок Range), веб-сервер берет полный ответ от 1С, вырезает из него указанный диапазон байтов, принудительно меняет код состояния с 200 на 206 Partial Content, добавляет заголовок Content-Range и отправляет этот усеченный пакет клиенту.

Попытки прописать статус 200 в коде 1С здесь бессильны, так как веб-сервер модифицирует ответ уже на выходе из приложения. Давайте рассмотрим способы борьбы с этим поведением.

Способ 2.1: Отключение поддержки докачки (диапазонов) на стороне 1С

Мы можем явно сообщить веб-серверу и клиенту, что наш HTTP-сервис не поддерживает отдачу контента частями. Для этого в заголовки ответа 1С необходимо добавить заголовок Accept-Ranges со значением none:


Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Accept-Ranges", "none");
Ответ.Заголовки.Вставить("Content-Type", "text/plain");
Ответ.УстановитьТелоИзСтроки("Ваш текст");

Возврат Ответ;

Увидев заголовок Accept-Ranges: none, корректно написанный клиент должен проигнорировать заголовок Range и запросить весь файл целиком, что приведет к возврату стандартного статуса 200 OK.

Способ 2.2: Настройка веб-сервера Apache для удаления заголовка Range

Если устройство невозможно перепрограммировать, и оно принудительно шлет заголовок Range, а веб-сервер Apache упорно переводит ответы в статус 206, мы можем заставить Apache полностью игнорировать этот заголовок для публикации 1С.

Для этого откройте конфигурационный файл httpd.conf вашего сервера Apache или найдите файл .htaccess в каталоге, куда выполнена публикация базы 1С. Добавьте в него следующую директиву:


<IfModule mod_headers.c>
    RequestHeader unset Range
</IfModule>

Также можно полностью отключить поддержку диапазонов для всего сервера или конкретного каталога с помощью директивы:

MaxRanges none

После сохранения конфигурации и перезапуска службы Apache веб-сервер перестанет видеть заголовок Range во входящих запросах и будет отдавать стандартный ответ 200 OK с полным телом сообщения.

Способ 2.3: Настройка веб-сервера IIS для очистки Range

В веб-сервере IIS (Internet Information Services) решить эту проблему можно с помощью официального модуля расширения URL Rewrite. Сделайте следующие шаги:

  1. Установите модуль URL Rewrite в вашу систему, если он еще не установлен.
  2. Откройте диспетчер служб IIS и выберите ваш сайт или конкретное виртуальное приложение с публикацией 1С.
  3. Перейдите в раздел URL Rewrite (Перенаправление URL).
  4. Создайте новое входящее правило (Inbound Rule) со следующими параметрами:
    • Укажите условие, соответствующее URL вашего HTTP-сервиса.
    • В разделе действий (Action) выберите изменение (очистку) серверной переменной HTTP_RANGE (установите ее значение пустым).

Очистка переменной HTTP_RANGE приведет к тому, что IIS обработает запрос как обычный GET-запрос без требования частичного контента и вернет клиенту статус 200 OK.

Способ 2.4: Сброс заголовка в Nginx (при использовании проксирования)

Очень часто перед веб-сервером IIS или Apache устанавливают производительный прокси-сервер Nginx. Если в вашей инфраструктуре используется Nginx, решить проблему со статусом 206 можно в один клик прямо в его конфигурационном файле nginx.conf.

Найдите блок location, отвечающий за перенаправление запросов к вашей публикации 1С, и добавьте туда строку, сбрасывающую заголовок Range:


location /your_1c_publication/ {
    proxy_pass http://backend_server;
    proxy_set_header Range "";
}

Это действие полностью сотрет заголовок Range из запроса клиента перед передачей его на бэкэнд (IIS или Apache). Веб-сервер приложения получит чистый запрос и вернет корректный ответ со статусом 200 OK.

---

Резюме

Мы детально изучили две важные проблемы при работе с HTTP-сервисами в 1С:Предприятии 8.3.

Для предотвращения нежелательного кодирования данных в Base64 всегда контролируйте заголовок Content-Type (используйте типы семейства text) или передавайте данные напрямую в бинарном формате через метод УстановитьТелоИзДвоичныхДанных().

Для борьбы с нежелательным статусом 206 Partial Content используйте отправку заголовка Accept-Ranges: none из 1С либо настройте фильтрацию входящего заголовка Range на уровне вашего веб-сервера (Apache, IIS или Nginx).

← На главную