Как правильно отправить POST-запрос с параметрами формы через HTTPСоединение в 1С?

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

При интеграции 1С со сторонними веб-сервисами и государственными порталами разработчики часто сталкиваются с ситуацией, когда при отправке запроса сервер возвращает стандартную начальную страницу или оглавление вместо запрошенных данных. Рассмотрим причины такого поведения и разберем, как правильно сформировать и отправить POST-запрос средствами встроенного языка 1С.

Анализ проблемы: почему сервер не видит параметры

Проанализируем типичную ошибку при работе с методом ОтправитьДляОбработки объекта HTTPСоединение. Если параметры запроса передаются в строке адреса (URL) или метод запроса не соответствует ожиданиям веб-сервера, сервер обрабатывает запрос как стандартное обращение к странице и возвращает ответ по умолчанию.

Для корректного взаимодействия с формами веб-сайтов необходимо соблюдать три основных правила:

  1. Параметры должны передаваться непосредственно в теле запроса, а не в строке URL.
  2. В заголовках запроса должен быть явно указан тип содержимого: Content-Type: application/x-www-form-urlencoded.
  3. Специальные символы в значениях параметров должны быть корректно закодированы.

Выясним причину важности заголовка Content-Type: без него веб-сервер не знает, каким парсером обрабатывать входящий поток данных, и игнорирует переданное тело, в результате чего возвращается пустая или начальная страница.

Базовый вариант решения с использованием временных файлов

Посмотрим на классический пример решения задачи, в котором тело запроса и ответ сервера сохраняются во временные файлы на диске:


// Создаем HTTP-соединение с сервером
HTTPСоединение = Новый HTTPСоединение("kgd.gov.kz");

// Получаем временный файл для передачи в теле POST-запроса
ФайлТелаЗапроса = ПолучитьИмяВременногоФайла();

// Записываем в файл содержимое тела запроса (параметры формы)
ТекстФайл = Новый ТекстовыйДокумент;
ТекстФайл.УстановитьТекст("limit=10&Code_ID=li_id_01012&Level_ID=li_cl_4+li_cl_click&FromAjax=true");
ТекстФайл.Записать(ФайлТелаЗапроса, КодировкаТекста.UTF8);

// Создаем соответствие для заголовков запроса
ЗаголовокЗапросаHTTP = Новый Соответствие;
ЗаголовокЗапросаHTTP.Вставить("Content-Type", "application/x-www-form-urlencoded");

// Инициализируем запрос и связываем его с файлом тела
HTTPЗапрос = Новый HTTPЗапрос("/tnved/otvet.php", ЗаголовокЗапросаHTTP);
HTTPЗапрос.УстановитьИмяФайлаТела(ФайлТелаЗапроса);

// Получаем временный файл для записи ответа
ФайлРезультат = ПолучитьИмяВременногоФайла();
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос, ФайлРезультат);

// Считываем результат из файла
ТекстовыйФайлОтвета = Новый ТекстовыйДокумент;
ТекстовыйФайлОтвета.Прочитать(ФайлРезультат, КодировкаТекста.UTF8);
СтрокаОтветаСервера = ТекстовыйФайлОтвета.ПолучитьТекст();

// Удаляем временные файлы после завершения работы
УдалитьФайлы(ФайлТелаЗапроса);
УдалитьФайлы(ФайлРезультат);

Обратите внимание: такие заголовки, как Host и Content-Length, заполнять вручную не требуется — платформа 1С рассчитывает и добавляет их автоматически при отправке запроса.

Оптимизированный вариант: работа в оперативной памяти без временных файлов

Разберем современный и более производительный способ отправки данных. Использование дисковой подсистемы для создания временных файлов создает лишнюю нагрузку на сервер 1С. Объект HTTPЗапрос предоставляет метод УстановитьТелоИзСтроки, а объект HTTPОтвет — метод ПолучитьТелоКакСтроку.

Посмотрим на оптимизированный пример кода:


// Настройка защищенного соединения для HTTPS
Защита = Новый ЗащищенноеСоединениеOpenSSL;
HTTPСоединение = Новый HTTPСоединение("kgd.gov.kz", 443, , , , 30, Защита);

// Формируем заголовки запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
Заголовки.Вставить("X-Requested-With", "XMLHttpRequest");

HTTPЗапрос = Новый HTTPЗапрос("/tnved/otvet.php", Заголовки);

// Подготавливаем строку параметров
СтрокаПараметров = "limit=10&Code_ID=li_id_01012&Level_ID=li_cl_4+li_cl_click&FromAjax=true";

// Передаем тело запроса напрямую из строки без BOM
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаПараметров, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

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

Если HTTPОтвет.КодСостояния = 200 Тогда
    СтрокаОтветаСервера = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
    // Обработка полученных данных
Иначе
    ВызватьИсключение "Ошибка HTTP: " + HTTPОтвет.КодСостояния;
КонецЕсли;

Важные нюансы при формировании HTTP-запросов

Рассмотрим подробнее технические детали, которые могут повлиять на успешность обмена:

  1. Метка порядка байтов (BOM): При записи строки в кодировке UTF-8 платформа может добавить невидимый символ BOM в начало тела запроса. Это приводит к тому, что имя первого переданного параметра будет искажено веб-сервером. Всегда используйте параметр ИспользованиеByteOrderMark.НеИспользовать при вызове метода УстановитьТелоИзСтроки.
  2. Кодирование спецсимволов (URL-encoding): Если значения параметров содержат пробелы, амперсанды, кириллицу или знаки плюс, их необходимо экранировать с помощью функции КодироватьСтроку(Значение, СпособКодированияСтроки.КодировкаURL). Знак + в теле формы интерпретируется сервером как пробел, поэтому для передачи реального плюса его нужно преобразовать в %2B.
  3. Использование HTTPS и перенаправления: Большинство современных ресурсов работает по защищенному протоколу. При обращении по незащищенному протоколу (порт 80) сервер вернет код перенаправления 301 или 302, который объект HTTPСоединение не обрабатывает автоматически. Всегда указывайте порт 443 и объект ЗащищенноеСоединениеOpenSSL при инициализации соединения с HTTPS-ресурсами.
  4. Имитация AJAX-запроса: При отправке параметров вида FromAjax=true бэкенд сайта часто проверяет служебный заголовок X-Requested-With: XMLHttpRequest. Его добавление гарантирует, что сервер вернет целевой фрагмент данных, а не полную HTML-страницу.
← На главную