При интеграции 1С со сторонними веб-сервисами и государственными порталами разработчики часто сталкиваются с ситуацией, когда при отправке запроса сервер возвращает стандартную начальную страницу или оглавление вместо запрошенных данных. Рассмотрим причины такого поведения и разберем, как правильно сформировать и отправить POST-запрос средствами встроенного языка 1С.
Проанализируем типичную ошибку при работе с методом ОтправитьДляОбработки объекта HTTPСоединение. Если параметры запроса передаются в строке адреса (URL) или метод запроса не соответствует ожиданиям веб-сервера, сервер обрабатывает запрос как стандартное обращение к странице и возвращает ответ по умолчанию.
Для корректного взаимодействия с формами веб-сайтов необходимо соблюдать три основных правила:
Content-Type: application/x-www-form-urlencoded.Выясним причину важности заголовка 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Ответ.КодСостояния;
КонецЕсли;
Рассмотрим подробнее технические детали, которые могут повлиять на успешность обмена:
ИспользованиеByteOrderMark.НеИспользовать при вызове метода УстановитьТелоИзСтроки.КодироватьСтроку(Значение, СпособКодированияСтроки.КодировкаURL). Знак + в теле формы интерпретируется сервером как пробел, поэтому для передачи реального плюса его нужно преобразовать в %2B.301 или 302, который объект HTTPСоединение не обрабатывает автоматически. Всегда указывайте порт 443 и объект ЗащищенноеСоединениеOpenSSL при инициализации соединения с HTTPS-ресурсами.FromAjax=true бэкенд сайта часто проверяет служебный заголовок X-Requested-With: XMLHttpRequest. Его добавление гарантирует, что сервер вернет целевой фрагмент данных, а не полную HTML-страницу.