При интеграции 1С с внешними веб-сервисами разработчики часто сталкиваются с необходимостью передать данные формы, используя стандарт multipart/form-data. В командной строке cURL это реализуется простым флагом -F, однако в языке 1С встроенного автоматического конструктора для такого формата долгое время не существовало. В этой статье мы подробно разберем, как правильно сформировать тело запроса вручную, настроить заголовки и избежать типичных ошибок, таких как ошибка 405.
Давайте проанализируем ситуацию, описанную в начале темы. Автор пытался отправить данные, просто склеив их в строку: grant_type=password&username=.... Такой формат называется application/x-www-form-urlencoded. Однако, если сервер ожидает multipart/form-data, он не сможет распарсить такую строку, так как этот стандарт требует наличия специальных разделителей (boundaries) и специфических заголовков для каждой части данных.
Разберем по шагам, как превратить обычный запрос в корректный multipart-запрос.
Для начала нам необходимо определить строку-разделитель. Она должна быть уникальной и не встречаться в самих передаваемых данных. Обычно используют строку вида ----ArbitraryBoundaryString. Этот разделитель мы укажем в основном заголовке запроса и будем использовать для отделения полей формы друг от друга.
Рассмотрим пример формирования заголовка Content-Type:
Разделитель = "----" + Строка(Новый УникальныйИдентификатор);
Запрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Разделитель);
Каждое поле формы (которое в cURL идет после флага -F) должно быть обернуто в разделители. Важно соблюдать строгую последовательность символов перевода строк. В 1С для этого обязательно используем комбинацию Символы.ВК + Символы.ПС (стандарт CRLF).
Структура одного блока данных выглядит следующим образом:
-- + РазделительContent-Disposition: form-data; name="ИмяПараметра"Выясним причину, по которой ручная сборка часто не работает: часто забывают закрывающий разделитель. В самом конце тела запроса разделитель должен заканчиваться еще двумя тире: --Разделитель--.
Посмотрим на пример реализации, который исправляет ошибку автора темы. Мы соберем тело запроса как текстовую строку, а затем установим ее в объект HTTPЗапрос.
// 1. Подготовка соединения
Соединение = Новый HTTPСоединение("адрес.ру", 443, , , , , Новый ЗащищенноеСоединениеOpenSSL);
// 2. Создание разделителя
Разделитель = "----" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
// 3. Формирование тела
ПереносСтроки = Символы.ВК + Символы.ПС;
ТелоЗапроса = "";
// Добавляем поле UserName
ТелоЗапроса = ТелоЗапроса + "--" + Разделитель + ПереносСтроки;
ТелоЗапроса = ТелоЗапроса + "Content-Disposition: form-data; name=""UserName""" + ПереносСтроки + ПереносСтроки;
ТелоЗапроса = ТелоЗапроса + Логин + ПереносСтроки;
// Добавляем поле Password
ТелоЗапроса = ТелоЗапроса + "--" + Разделитель + ПереносСтроки;
ТелоЗапроса = ТелоЗапроса + "Content-Disposition: form-data; name=""Password""" + ПереносСтроки + ПереносСтроки;
ТелоЗапроса = ТелоЗапроса + Пароль + ПереносСтроки;
// Закрывающий разделитель
ТелоЗапроса = ТелоЗапроса + "--" + Разделитель + "--" + ПереносСтроки;
// 4. Настройка запроса
Запрос = Новый HTTPЗапрос("ресурс");
Запрос.Заголовки.Вставить("accept", "text/plain");
Запрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Разделитель);
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// 5. Отправка
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Рассмотрим ситуацию, когда даже при правильном теле запроса сервер возвращает 405 ошибку. В 1С это часто связано с автоматическим редиректом. Если вы отправляете запрос на адрес.ру/ресурс, а сервер ожидает адрес.ру/ресурс/ (со слэшем в конце), он может отправить команду перенаправления (код 301 или 302). При выполнении редиректа клиент 1С может изменить метод с POST на GET, что и приводит к ошибке "Метод не разрешен".
Рекомендация: Всегда проверяйте точный URL ресурса в документации API или с помощью инструментов отладки, таких как Postman или Fiddler. Как было правильно замечено в обсуждении, использование сниффера трафика позволяет увидеть "сырой" (raw) текст запроса, который генерирует cURL, и в точности воспроизвести его в 1С.
Если ваша задача усложнится и потребуется передать не просто текст, а файл (флаг -F "file=@path/to/file"), метод УстановитьТелоИзСтроки не подойдет, так как он может повредить бинарную структуру файла при кодировании. В этом случае необходимо использовать ДвоичныеДанные.
Проанализируем алгоритм для файлов:
ПолучитьДвоичныеДанныеИзСтроки.ДвоичныеДанные.ПотокВПамяти (доступно в новых версиях платформы 8.3.18+).Запрос.УстановитьТелоИзДвоичныхДанных().Если ручное формирование кажется слишком громоздким, стоит рассмотреть готовые инструменты. В сообществе разработчиков 1С популярна библиотека Connector (доступна на GitHub), которая инкапсулирует всю сложность формирования multipart-запросов. С ее помощью отправка данных формы сводится к заполнению обычного соответствия (Map) с параметрами, а библиотека сама заботится о разделителях, кодировках и бинарных данных.
Подводя итог, можно сказать, что реализация multipart/form-data в 1С требует особого внимания к деталям: строгой последовательности CRLF, правильному оформлению заголовков внутри тела и обязательному указанию boundary в основном заголовке запроса. Понимание этих основ позволит вам успешно интегрировать 1С с любыми современными веб-сервисами.