Перейти к содержимому

Тело HTTP-запроса может прийти в UTF-16LE — читать бинарно

Директивный

#http#кодировки

В HTTP-сервисах-провайдерах не полагаться на ПолучитьТелоКакСтроку() с ожидаемой кодировкой. Тело читать как двоичные данные, пробовать UTF-8 и при обнаружении Символ(0) перечитывать как UTF-16LE.

Тело, которое отправитель (в том числе сама платформа 1С через ШаблонНастройкиВторогоФактораАутентификации) собрал как UTF-8, в отдельных сборках приходит в UTF-16LE. Признаки:

  • NUL-байты между ASCII-символами;
  • длина тела ровно вдвое больше визуально ожидаемой;
  • JSON-парсер падает: «Непредвиденный символ при чтении JSON»;
  • запись такого тела в ЖР ломается XDTO-ошибкой (см. NUL-байт ломает XML/XDTO).

Детект по Символ(0) работает и без BOM — поэтому он в шаблоне основной. Если хочется точнее, сначала посмотрите первые байты тела: FF FE — UTF-16LE с BOM, EF BB BF — UTF-8 с BOM; но рассчитывать на BOM нельзя — в реальном инциденте его не было.

Когда парсер падает на «нормальном с виду» JSON, не спорьте со строкой — посмотрите на байты:

  • длина тела вдвое больше ожидаемой по содержимому — почти наверняка UTF-16;
  • залогируйте размер ПолучитьТелоКакДвоичныеДанные().Размер() и длину строки после чтения — расхождение ×2 видно сразу;
  • сырое тело в ЖР не пишите, пока не вычистили NUL — иначе сломается сам журнал.

HTTP-сервис-провайдер шаблона второго фактора аутентификации: шаблон создавался в 1С через HTTPЗапрос.УстановитьТелоИзСтроки(json, "UTF-8"), но платформа прислала тело провайдеру в UTF-16LE — на стороне приёмника JSON-парсер падал с «Непредвиденный символ при чтении JSON», хотя отправитель «точно отправлял UTF-8». Кодировку, которую платформа выбирает сама, контрактом не зафиксируешь — поэтому правило безусловное: тело читается бинарно с детектом, а не «как договорились».

Если канал гарантированно контролируется вами и кодировка тела фиксирована контрактом — бинарный детект избыточен. Для внешних/платформенных провайдеров правило действует всегда.