При разработке HTTP-сервисов в среде 1С:Предприятие 8.3 разработчики часто сталкиваются с ситуацией, когда при получении POST-запроса стандартное свойство ПараметрыЗапроса (тип ФиксированноеСоответствие) оказывается пустым. Это происходит потому, что платформа автоматически заполняет это свойство только параметрами, переданными в строке URL (после знака вопроса). Если же данные передаются в теле запроса (body) в формате application/x-www-form-urlencoded, нам необходимо разбирать их самостоятельно.
В данной статье мы подробно рассмотрим, как программно извлечь данные из тела запроса, превратить их в удобную структуру и корректно обработать вложенные данные, такие как XML-строки.
Разберем ситуацию: сторонний сервис или сайт отправляет запрос на ваш HTTP-сервис. В заголовках указан метод POST, а тело запроса выглядит примерно так: xml_data=...&card=PT_EPOS&mer_no=ok22. Для платформы 1С это единый блок данных. Она не «парсит» его автоматически в коллекцию параметров, так как это данные тела, а не заголовка запроса. Чтобы работать с этими данными, мы должны сначала получить их как сырую строку, а затем применить алгоритм декомпозиции.
Первым делом в методе-обработчике (например, ЛюбойМетод(Запрос)) нам нужно извлечь содержимое. Рассмотрим, как это сделать правильно:
// Получаем тело запроса в виде строки
// Важно: если ожидаются кириллические символы, лучше явно указать кодировку
ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Если мы проанализируем переменную ТелоЗапроса, мы увидим длинную строку, где параметры разделены символом амперсанда (&), а ключи и значения разделены знаком равенства (=).
Проанализируем самый быстрый и очевидный способ разделения строки. Мы воспользуемся встроенной функцией СтрРазделить, которая позволяет превратить строку в массив по разделителю.
// Разделяем строку на массив пар "ключ=значение"
МассивПараметров = СтрРазделить(ТелоЗапроса, "&");
// Создаем структуру для хранения результата
СтруктураРезультат = Новый Структура;
Для Каждого СтрокаПараметр Из МассивПараметров Цикл
// Каждую пару разделяем по первому символу "="
ПозицияРазделителя = СтрНайти(СтрокаПараметр, "=");
Если ПозицияРазделителя > 0 Тогда
Ключ = Лев(СтрокаПараметр, ПозицияРазделителя - 1);
Значение = Сред(СтрокаПараметр, ПозицияРазделителя + 1);
// Вставляем в структуру.
// Внимание: имя ключа должно соответствовать правилам имен в 1С!
СтруктураРезультат.Вставить(Ключ, Значение);
КонецЕсли;
КонецЦикла;
Рассмотрим критически важный нюанс, который часто упускают. Данные в формате x-www-form-urlencoded передаются в закодированном виде. Например, вместо пробела будет символ + или %20, а вместо знаков < и > в XML — последовательности %3C и %3E. Если просто использовать СтрРазделить, ваш XML-текст будет испорчен и не прочитается стандартным средством ЧтениеXML.
Для решения этой проблемы мы должны использовать функцию РаскодироватьСтроку. Модернизируем наш алгоритм:
Функция РазобратьТелоЗапроса(Знач ТелоСтрокой) Экспорт
Результат = Новый Соответствие; // Используем Соответствие, т.к. ключи могут быть любыми
МассивПар = СтрРазделить(ТелоСтрокой, "&");
Для Каждого Пара Из МассивПар Цикл
Поз = СтрНайти(Пара, "=");
Если Поз > 0 Тогда
Ключ = Лев(Пара, Поз - 1);
ЗначениеЗакодированное = Сред(Пара, Поз + 1);
// Заменяем "+" на пробел, так как РаскодироватьСтроку может этого не сделать
// в зависимости от специфики отправителя
ЗначениеЗакодированное = СтрЗаменить(ЗначениеЗакодированное, "+", " ");
// Декодируем спецсимволы (URL Decode)
Значение = РаскодироватьСтроку(ЗначениеЗакодированное, СпособКодированияСтроки.URLАнкор);
Результат.Вставить(Ключ, Значение);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Выясним, как работать с параметром, который содержит XML-данные (в нашем примере это xml_data). После того как мы раскодировали строку и получили «чистый» XML, мы можем использовать стандартную фабрику XDTO для превращения текста в объект 1С.
// Предположим, Параметры - это Соответствие, полученное на предыдущем шаге
ТекстXML = Параметры.Получить("xml_data");
Если ТекстXML <> Неопределено Тогда
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(ТекстXML);
Попытка
// Используем фабрику XDTO для чтения
ОбъектДанных = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
// Теперь в переменной ОбъектДанных находится объектная модель вашего XML
Исключение
ЗаписьЖурналаРегистрации("Ошибка разбора XML", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Проанализируем несколько советов, которые помогут сделать интеграцию более надежной:
Запрос.Заголовки.Получить("Content-Type").notify-signature), метод Структура.Вставить() вызовет ошибку, так как имя свойства структуры не может содержать дефис. Соответствие лишено этого ограничения.& или = как часть текстовых данных, убедитесь, что отправляющая сторона корректно их экранирует, иначе простой СтрРазделить по этим символам «разрежет» ваш XML в непредсказуемых местах.Таким образом, мы разобрали полный цикл обработки POST-запроса: от получения сырых данных из тела до восстановления структуры и парсинга XML. Использование функций СтрРазделить и РаскодироватьСтроку является надежным стандартом для обработки форм, отправляемых веб-сайтами в 1С.