Как обработать POST-запрос в HTTP-сервисе 1С, если пробелы заменяются на плюсы, а в начале строки появляется "text="?

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

При интеграции 1С с внешними системами через HTTP-сервисы разработчики часто сталкиваются с ситуацией, когда отправленный JSON-пакет приходит в базу в «искаженном» виде. Вместо аккуратной структуры мы получаем строку, где все пробелы заменены на знаки «плюс» (+), а в самом начале строки добавляется странный префикс (например, text= или data=). В результате стандартный метод десериализации JSON выдает ошибку, и прочитать данные не удается.

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

Выясняем причину: почему искажаются данные?

Описанные симптомы однозначно указывают на то, что отправляющая сторона (клиент) передает данные с заголовком Content-Type: application/x-www-form-urlencoded вместо стандартного application/json.

Формат application/x-www-form-urlencoded — это стандартный способ кодирования данных HTML-форм при отправке POST-запросов. По спецификации этого формата:

  1. Данные упаковываются в виде пар «ключ=значение». В случае автора темы весь JSON-текст был помещен в переменную (поле формы) с именем text. Из-за этого в начале строки и появляется префикс text=.
  2. Все пробелы в значениях заменяются на символы «плюс» (+).
  3. Специальные символы (включая фигурные скобки, кавычки и двоеточия, из которых состоит JSON) кодируются в шестнадцатеричный URL-формат (например, кавычка превращается в %22, а фигурная скобка — в %7B).

Когда мы вызываем метод Запрос.ПолучитьТелоКакСтроку(), платформа 1С возвращает нам «сырое» тело POST-запроса в том виде, в котором оно пришло от клиента. Если клиент закодировал данные как форму, мы и получаем закодированную строку.

Проанализируем два способа решения этой проблемы: правильный (настройка клиента) и обходной (обработка внутри 1С).

Решение 1. Исправление на стороне отправителя (Рекомендуемый путь)

Самый правильный и архитектурно верный способ решить проблему — заставить отправляющую систему передавать JSON в «чистом» виде без лишнего кодирования. Если вы сами настраиваете интеграцию (например, тестируете запросы в Postman) или можете повлиять на сторонних разработчиков, выполните следующие действия:

  1. Установите заголовок запроса: В заголовках (Headers) HTTP-запроса обязательно укажите Content-Type: application/json.
  2. Измените формат тела запроса: Передавайте JSON-строку как «сырые» данные (Raw Body), а не как параметры формы (form-data или x-www-form-urlencoded). В Postman для этого нужно перейти на вкладку Body, выбрать переключатель raw и в выпадающем списке справа выбрать тип JSON.

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


// В HTTP-сервисе 1С при правильном Content-Type:
СтрокаJSON = Запрос.ПолучитьТелоКакСтроку("UTF-8");

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

Если отправителем выступает другая база 1С, убедитесь, что при формировании запроса вы явно задаете заголовок и передаете JSON напрямую в тело:


HTTPЗапрос = Новый HTTPЗапрос("/hs/MyService/v1/data");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8);

Решение 2. Обработка данных на стороне 1С (Если отправителя нельзя изменить)

Бывают ситуации, когда веб-сервис принимает запросы от сторонней системы (например, платежного шлюза, мессенджера или CRM), логику работы которой изменить невозможно. Если интеграция жестко требует отправки в формате application/x-www-form-urlencoded, нам придется корректно разбирать такое тело запроса на стороне 1С.

Простая замена плюсов через СтрЗаменить(СтрокаЗапроса, "+", "%20") и ручное отсечение префикса — рабочий вариант, но он ненадежен. Что если имя параметра изменится или в запросе придет несколько полей? Рассмотрим универсальный и безопасный алгоритм разбора входящих urlencoded-данных.

Создадим вспомогательную функцию, которая преобразует сырое тело запроса в удобную структуру (или соответствие) параметров:


// Функция разбирает тело x-www-form-urlencoded в соответствие параметров
Функция РазобратьТелоFormUrlEncoded(Знач ТелоСтрокой) Экспорт
    Результат = Новый Соответствие;
    
    // Шаг 1. Согласно стандарту urlencoded, пробелы кодируются как "+".
    // Заменяем их на "%20", чтобы встроенная функция РаскодироватьСтроку отработала корректно.
    // Настоящие символы "+" к этому моменту уже закодированы отправителем в "%2B", поэтому они не пострадают.
    ТелоСтрокой = СтрЗаменить(ТелоСтрокой, "+", "%20");
    
    // Шаг 2. Разделяем параметры, если их передается несколько (разделитель "&")
    МассивПар = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ТелоСтрокой, "&");
    
    Для Каждого Параметр Из МассивПар Цикл
        ПозицияРавно = Найти(Параметр, "=");
        Если ПозицияРавно > 0 Тогда
            // Выделяем имя ключа и его значение
            КлючЗакодированный = Лев(Параметр, ПозицияРавно - 1);
            ЗначениеЗакодированное = Прав(Параметр, СтрДлина(Параметр) - ПозицияРавно);
            
            // Шаг 3. Декодируем ключ и значение из URL-формата
            Ключ = РаскодироватьСтроку(КлючЗакодированный, СпособКодированияСтроки.КодировкаURL, "UTF-8");
            Значение = РаскодироватьСтроку(ЗначениеЗакодированное, СпособКодированияСтроки.КодировкаURL, "UTF-8");
            
            Результат.Вставить(Ключ, Значение);
        Иначе
            // Параметр без значения
            Ключ = РаскодироватьСтроку(Параметр, СпособКодированияСтроки.КодировкаURL, "UTF-8");
            Результат.Вставить(Ключ, "");
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

Теперь применим разработанную функцию в обработчике нашего HTTP-сервиса. Мы извлечем закодированное тело, превратим его в соответствие параметров, получим нужный JSON по ключу и успешно его распарсим:


// Обработчик метода POST HTTP-сервиса
Функция ШаблонМетодаPOST(Запрос)
    
    // Всегда явно указываем кодировку UTF-8 при чтении тела запроса
    ТелоСтрокой = Запрос.ПолучитьТелоКакСтроку("UTF-8");
    
    // Парсим параметры формы
    ПараметрыФормы = РазобратьТелоFormUrlEncoded(ТелоСтрокой);
    
    // Ищем наш JSON, отправленный в параметре "text"
    СтрокаJSON = ПараметрыФормы.Получить("text");
    
    Если СтрокаJSON = Неопределено Тогда
        // Если параметр не найден, попробуем прочитать тело напрямую (вдруг клиент исправили)
        СтрокаJSON = ТелоСтрокой;
    КонецЕсли;
    
    // Пытаемся прочитать JSON
    Попытка
        ЧтениеJSON = Новый ЧтениеJSON();
        ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
        СтруктураЗапроса = ПрочитатьJSON(ЧтениеJSON);
        ЧтениеJSON.Закрыть();
        
        // Здесь выполняем основную бизнес-логику с полученной структурой...
        
        Ответ = Новый HTTPСервисОтвет(200);
        Ответ.УстановитьТелоИзСтроки("Данные успешно обработаны", КодировкаТекста.UTF8);
        Возврат Ответ;
        
    Исключение
        // Обработка ошибки парсинга JSON
        Ответ = Новый HTTPСервисОтвет(400);
        Ответ.УстановитьТелоИзСтроки("Ошибка декодирования JSON: " + ОписаниеОшибки(), КодировкаТекста.UTF8);
        Возврат Ответ;
    КонецПопытки;

КонецФункции

Важные нюансы при работе с кодировкой

При обмене данными по протоколу HTTP крайне важно следить за кодировками. Обратите внимание на следующие моменты:

Таким образом, мы детально разобрали особенности обработки входящих POST-запросов. Понимание стандартов кодирования веб-данных позволяет легко устранять подобные технические сложности и создавать надежные интеграционные механизмы.

← На главную