Как правильно передавать кириллицу в заголовках HTTP-запросов в 1С?

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

При разработке мобильных приложений и систем интеграции на платформе 1С программисты часто сталкиваются с неприятной ситуацией: при попытке передать строку с кириллическими символами (например, ФИО пользователя или номер автомобиля) в заголовке HTTPЗапрос, сервер 1С получает «несуразицу» или «кракозябры». Вместо ожидаемого «А 111 АА» в отладчике на стороне сервера мы видим нечто вроде «Рђ 111 РђРђ». В этой статье мы детально разберем, почему так происходит и какими способами можно гарантированно доставить текстовые данные без искажений.

Выясняем причину: почему заголовки «портят» текст?

Для начала проанализируем техническую сторону вопроса. Согласно международным стандартам протокола HTTP (в частности, RFC 7230), значения заголовков должны содержать только символы из набора ASCII. Официально кириллица напрямую в заголовках не поддерживается. Когда мы в 1С пишем Заголовки.Вставить("AutoNum", "А 111 АА"), мобильная платформа пытается передать эти данные в кодировке UTF-8. Однако принимающая сторона (веб-сервер IIS или Apache, а затем и сама 1С) часто интерпретирует эти байты в своей стандартной локальной кодировке (обычно Windows-1251).

В результате каждый двухбайтовый символ кириллицы из UTF-8 превращается в два отдельных непонятных символа из расширенной таблицы ASCII. Именно поэтому мы видим «Рђ» вместо «А». Попытки указать charset=utf-8 в Content-Type обычно не помогают, так как этот заголовок описывает только тело запроса, но не сами заголовки.

Способ 1: Использование функции КодироватьСтроку (URL-Encode)

Наиболее правильным «нативным» способом передачи специальных символов в HTTP-заголовках является их кодирование в формат URL-encoded. Давайте рассмотрим, как это реализовать. Начиная с версии платформы 8.3.9.1818, метод КодироватьСтроку стал доступен и на мобильной платформе.

Рассмотрим по шагам процесс кодирования на стороне отправителя:


// На стороне мобильного приложения
ЗначениеДляЗаголовка = "А 111 АА";
КодированноеЗначение = КодироватьСтроку(ЗначениеДляЗаголовка, СпособКодированияСтроки.КодировкаURL, "UTF-8");
Заголовки.Вставить("AutoNum", КодированноеЗначение);

Теперь проанализируем, что нужно сделать на стороне сервера 1С, чтобы получить исходную строку. Сервер получит строку вида %D0%90%20111%20%D0%90%D0%90. Ее необходимо раскодировать:


// На стороне сервера (HTTP-сервис)
КодированноеЗначение = Запрос.Заголовки.Получить("AutoNum");
Если КодированноеЗначение <> Неопределено Тогда
    ЧистоеЗначение = РаскодироватьСтроку(КодированноеЗначение, СпособКодированияСтроки.КодировкаURL);
    // Теперь ЧистоеЗначение содержит "А 111 АА"
КонецЕсли;

Способ 2: Кодирование в Base64 (Самый надежный метод)

Если по каким-то причинам стандартное URL-кодирование не проходит через прокси-серверы или брандмауэры, мы можем использовать преобразование в Base64. Этот метод превращает любую строку в набор безопасных ASCII-символов (латиница и цифры), которые гарантированно не будут изменены промежуточными узлами.

Разберем пример реализации через двоичные данные:


// Кодирование на клиенте
Текст = "А 111 АА";
ДвоичныеДанные = ДвоичныеДанныеИзСтроки(Текст, КодировкаТекста.UTF8);
Base64Значение = Base64Строка(ДвоичныеДанные);
Заголовки.Вставить("X-AutoNum", Base64Значение);

// Декодирование на сервере
Base64Значение = Запрос.Заголовки.Получить("X-AutoNum");
Если Base64Значение <> Неопределено Тогда
    ДвоичныеДанныеСервер = Base64Значение(Base64Значение);
    ЧистоеЗначение = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеСервер, КодировкаТекста.UTF8);
КонецЕсли;

Важный момент: Для передачи пользовательских данных в заголовках рекомендуется использовать префикс X- (например, X-AutoNum), хотя в современных стандартах это не является обязательным, это помогает отделить ваши данные от стандартных HTTP-заголовков.

Способ 3: Перенос данных из заголовков в тело запроса (POST)

Как справедливо отметил автор темы на форуме, проблему можно обойти радикально — перестать использовать заголовки для передачи кириллицы и перенести эти данные в тело запроса. Если вы используете метод GET, у вас нет тела запроса. В этом случае стоит рассмотреть возможность перехода на метод POST.

Давайте посмотрим на пример формирования JSON в теле запроса:


// На мобильном устройстве
Запрос = Новый HTTPЗапрос("/hs/MyService/v1/SaveData");
ПараметрыДанных = Новый Структура;
ПараметрыДанных.Вставить("AutoNum", "А 111 АА");
ПараметрыДанных.Вставить("UserName", "Иван Иванов");

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ПараметрыДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();

Запрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Отправляем POST запрос

Этот способ является наиболее устойчивым к проблемам с кодировками, так как механизм 1С при работе с телом запроса корректно обрабатывает UTF-8 «из коробки» при условии правильного указания кодировки в методе УстановитьТелоИзСтроки.

Влияние веб-сервера (IIS и Apache)

Проанализируем ситуацию, когда даже после кодирования данные приходят искаженными. Часто проблема кроется в настройках веб-сервера, который выступает шлюзом для 1С.

  1. IIS: Может пытаться интерпретировать заголовки на основе системной локали Windows. Проверьте настройки в web.config в секции <globalization>.
  2. Apache: Может иметь модули перекодировки (например, mod_charset_lite), которые принудительно меняют входящий поток.

Если вы используете кодирование (URL-Encode или Base64), влияние настроек веб-сервера сводится к минимуму, так как передаются только «безопасные» символы латиницы.

Резюме и рекомендации

Подведем итоги нашего исследования:

Выбрав один из предложенных вариантов, мы обеспечим стабильную работу обмена данными между мобильными устройствами и сервером 1С вне зависимости от сложности используемых символов.

← На главную