Почему возникает ошибка 400 Bad Request при отправке XML файла по HTTP в 1С и как её исправить?

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

При интеграции 1С с внешними веб-сервисами разработчики часто сталкиваются с ситуацией, когда метод ОтправитьДляОбработки() или POST-запрос возвращает код состояния HTTP 400 Bad Request или 500 Internal Server Error. Проанализируем основные причины этой проблемы и разберем по шагам, как правильно формировать и отправлять XML-данные из 1С.

1. Проблема с маркером BOM (Byte Order Mark) в XML

При создании XML-файла через объект ЗаписьXML и сохранении его на диск в начало файла часто добавляется маркер последовательности байтов (BOM). Большинство сторонних веб-серверов и REST API не ожидают наличие BOM перед стандартным объявлением <?xml version="1.0" encoding="UTF-8"?> и отклоняют весь запрос как невалидный с ошибкой 400.

Рассмотрим, как избежать использования BOM и исключить промежуточные временные файлы, сформировав XML непосредственно в оперативной памяти:


// Формируем XML в строковую переменную
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку("UTF-8");
Запись.ЗаписатьОбъявлениеXML();

Запись.ЗаписатьНачалоЭлемента("scoreList");
// ... Заполняем структуру XML ...
Запись.ЗаписатьКонецЭлемента(); // scoreList

СтрокаXML = Запись.Закрыть();

// Передаем строку в запрос с явным указанием отключать BOM
HTTPЗапрос = Новый HTTPЗапрос(ОтносительныйURL);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаXML, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

2. Ручная установка заголовка Content-Length

Выясним причину дублирования или искажения заголовков запроса. В платформе 1С при вызове методов УстановитьТелоИзСтроки() или УстановитьИмяФайлаТела() длина передаваемых данных рассчитывается автоматически, и заголовок Content-Length формируется самой платформой.

Если явно добавлять Content-Length в соответствие заголовков (особенно передавая числовое значение ДвоичныеДанные.Размер()), сервер получает продублированный или некорректно сформированный заголовок HTTP-пакета. Это неизбежно вызывает ошибку 400 Bad Request. Ручное добавление Content-Length выполнять не требуется.

3. Ошибка в порядке параметров конструктора HTTPСоединение

Посмотрим на инициализацию объекта HTTPСоединение. Одной из самых распространенных ошибок является неправильное количество запятых при настройке параметров соединения.

Разберем параметры конструктора HTTPСоединение по порядку:

  1. Сервер (Имя хоста)
  2. Порт
  3. Пользователь
  4. Пароль
  5. Прокси
  6. Таймаут
  7. ЗащищенноеСоединение (Объект ЗащищенноеСоединениеOpenSSL)
  8. ИспользоватьАутентификациюОС (Булево)

Если передать Истина в качестве 8-го параметра, платформа включит NTLM/Kerberos аутентификацию Windows, вместо создания защищенного HTTPS-соединения. Для работы по протоколу HTTPS нужно передавать объект защищенного соединения в 7-й параметр:


// Правильная инициализация HTTPS-соединения
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
HTTPСоединение = Новый HTTPСоединение("example.com", 443, , , , , ЗащищенноеСоединение);

4. Некорректный формат относительного URL

Проанализируем формирование пути в объекте HTTPЗапрос. Относительный адрес (URL без указания домена) обязателен к передаче со начальным слэшем /. Если передать путь вида api/v1/import вместо /api/v1/import, веб-сервер воспринимает начальную строку HTTP-запроса как синтаксически неверную и возвращает код 400.

5. Преобразование типов данных в XML

При обходе данных и формировании узлов XML использование простой функции Строка() для всех подряд значений приводит к нарушению XSD-схемы на стороне сервера:

  1. Числа: 1С преобразует числа с неразрывным пробелом в качестве разделителя тысяч (например, 1 500,50). Для XML следует форматировать числа без пробелов и с точкой в качестве разделителя дробей: Формат(Стр.План, "ЧГ=0; ЧРД=.").
  2. Даты: Преобразуйте даты в формат ISO 8601 (YYYY-MM-DDTHH:mm:ss).
  3. Булевы значения: Передавайте строки true или false вместо Истина и Ложь.

6. Чтение детального текста ошибки от сервера

При получении кодов состояния 400 или 500 веб-сервер почти всегда возвращает описание проблемы в теле ответа (например, информацию об отсутствующих обязательных полях XML). Проанализируем, как извлечь этот текст для отладки:


Результат = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);

Если Результат.КодСостояния > 299 Тогда
    ТекстОтвета = Результат.ПолучитьТелоКакСтроку();
    Сообщить("Код состояния: " + Строка(Результат.КодСостояния));
    Сообщить("Текст ответа сервера: " + ТекстОтвета);
КонецЕсли;

Считывание тела ответа позволит быстро выявить точные причины, по которым внешний сервис отвергает сформированный XML-документ.

← На главную