Как в 1С отправить POST-запрос form-data аналогично Postman

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

При интеграции 1С с внешними веб-сервисами разработчики часто сталкиваются с необходимостью отправки данных в формате multipart/form-data. В популярных инструментах вроде Postman это делается за пару кликов, однако в среде 1С:Предприятие реализация такого запроса требует "ручной" сборки тела сообщения и строгого соблюдения протокола HTTP. В этой статье мы подробно разберем, как правильно сформировать такой запрос, настроить заголовки и обработать ответы сервера, включая перенаправления.

Понятие multipart/form-data и Boundary

Формат multipart/form-data используется для передачи набора пар "ключ-значение", а также файлов. Основная особенность заключается в том, что все тело запроса разделено на части специальной строкой-разделителем, которая называется boundary. Проанализируем ключевые правила формирования этих разделителей:

  1. В заголовке Content-Type указывается параметр boundary, который определяет строку-разделитель.
  2. В самом теле запроса перед каждым блоком данных эта строка должна начинаться с двух дефисов (--).
  3. Последний разделитель в теле запроса должен иметь два дефиса как в начале, так и в конце (--boundary--).
  4. Каждая секция внутри тела должна содержать заголовок Content-Disposition с указанием имени поля (name).

Разбор типовой ошибки и поиск решения

Рассмотрим ситуацию, когда при отправке логина и пароля сервер возвращает ошибку 500 или 400. Часто это связано с некорректным форматированием строк. Выясним причину: в стандарте HTTP строки должны разделяться парой символов CRLF (возврат каретки и перевод строки). В 1С при использовании многострочной строки (через вертикальную черту |) может вставляться только символ перевода строки LF, что приводит к нарушению структуры запроса.

Посмотрим на пример правильного формирования тела запроса с использованием массива строк, что позволяет гарантированно вставить нужные символы разделителей:


boundary = "wL36Yn8afVp8Ag7AmP8qZ0SA4n1v9T";
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + boundary);

МассивЗапроса = Новый Массив;
МассивЗапроса.Добавить("--" + boundary);
МассивЗапроса.Добавить("Content-Disposition: form-data; name=""login""");
МассивЗапроса.Добавить(""); // Пустая строка отделяет заголовки секции от данных
МассивЗапроса.Добавить("LoginApi");
МассивЗапроса.Добавить("--" + boundary);
МассивЗапроса.Добавить("Content-Disposition: form-data; name=""password""");
МассивЗапроса.Добавить("");
МассивЗапроса.Добавить("PassApi");
МассивЗапроса.Добавить("--" + boundary + "--");
МассивЗапроса.Добавить("");

СтрокаДляЗапроса = СтрСоединить(МассивЗапроса, Символы.ВК + Символы.ПС);

Реализация защищенного соединения и итоговый код

Если целевой сервер работает по протоколу HTTPS (порт 443), необходимо использовать объект ЗащищенноеСоединениеOpenSSL. Проанализируем законченный пример кода, который успешно решает задачу авторизации и получения JSON-данных:


Сервер = "site.com";
Порт = 443;
Сервис = "/api/json/getData/";

// Настройка защищенного соединения
Ssl = Новый ЗащищенноеСоединениеOpenSSL;
Прокси = Новый ИнтернетПрокси(Ложь);
СоединениеHTTP = Новый HTTPСоединение(Сервер, Порт, , , Прокси, , Ssl);

// Уникальный разделитель
Разделитель = "dcb833ea-be63-4b00-9b57-aa2c0749aa5a";

Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Разделитель);

ЗапросHTTP = Новый HTTPЗапрос(Сервис, Заголовки);

// Формируем тело запроса вручную
ТелоЗапроса = "--" + Разделитель + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроса + "Content-Disposition: form-data; name=""login""" + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроса + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроса + "LoginApi" + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроса + "--" + Разделитель + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроса + "Content-Disposition: form-data; name=""password""" + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроca + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроса + "PassApi" + Символы.ВК + Символы.ПС;
ТелоЗапроса = ТелоЗапроса + "--" + Разделитель + "--";

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

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

Если Результат.КодСостояния = 200 Тогда
    ДанныеJSON = Результат.ПолучитьТелоКакСтроку();
    // Дальнейшая обработка полученного JSON
ИначеЕсли Результат.КодСостояния = 302 Тогда
    // Обработка редиректа, если сервер перенаправляет запрос
    НовыйАдрес = Результат.Заголовки.Получить("Location");
    Сообщить("Требуется перенаправление на: " + НовыйАдрес);
КонецЕсли;

Обработка редиректов (Код состояния 302)

Ситуация, когда сервер возвращает код 302 Found, означает временное перенаправление. В этом случае необходимо извлечь новый адрес из заголовка Location. Рассмотрим подробнее: если вы получили 302 при попытке авторизации, это может означать, что сервер успешно принял данные и отправляет вас на страницу личного кабинета или к результатам поиска.

Важный нюанс: при выполнении повторного запроса по адресу из Location, 1С (как и многие другие клиенты) может изменить метод с POST на GET. Если API требует сохранения метода POST и повторной отправки тела данных, вам необходимо создать новый HTTPЗапрос и снова установить в него тело и заголовки.

Работа с кодировками и Byte Order Mark (BOM)

При отправке текстовых данных крайне важно использовать КодировкаТекста.UTF8. Однако многие веб-серверы некорректно воспринимают наличие метки BOM (три байта в начале строки, указывающие на кодировку). В методе УстановитьТелоИзСтроки() третьим параметром следует всегда передавать ИспользованиеByteOrderMark.НеИспользовать. Это исключит появление лишних символов в начале запроса, которые часто становятся причиной ошибки 400 (Bad Request).

Как передать файл в multipart-запросе

Если ваша задача усложняется необходимостью передать файл (например, изображение), метод УстановитьТелоИзСтроки не подойдет, так как он может повредить двоичные данные. В этом случае необходимо:

  1. Использовать объект ЗаписьДанных для записи текстовых заголовков разделов в буфер (в кодировке UTF-8).
  2. Записывать содержимое файла как ДвоичныеДанные непосредственно в тот же поток.
  3. Завершать поток закрывающим разделителем --boundary--.
  4. Устанавливать готовое тело в запрос методом УстановитьТелоИзДвоичныхДанных.

Такой подход гарантирует, что файл дойдет до сервера в неизменном виде, а текстовые поля будут корректно интерпретированы.

Заключение

Для успешной реализации form-data запроса в 1С важно помнить о строгом формате разделителей boundary, использовании правильных переносов строк CRLF и отключении метки BOM. Тщательно проверяйте заголовки в Postman (вкладка Headers) и воспроизводите их в коде 1С, включая такие параметры, как Content-Length и User-Agent, если этого требует спецификация API вашего контрагента.

← На главную