Как передать URL с "http://" в заголовке Referer при работе с HTTPСоединение в 1С?

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

При отправке HTTP-запросов из 1С к сторонним веб-сервисам часто требуется передавать специальные заголовки, например, Referer или User-Agent. Однако разработчики нередко сталкиваются с ситуацией, когда при передаче URL с указанием протокола (http:// или https://) платформа 1С выдает системную ошибку: "ошибка в параметре №3" (или аналогичную ошибку параметров метода).

В этой статье разберем причину возникновения данной проблемы, рассмотрим правильный способ передачи HTTP-заголовков через объект Соответствие, а также проанализируем важные нюансы работы с соединением и альтернативные механизмы отправки запросов.

Причина возникновения ошибки при текстовой передаче заголовков

Рассмотрим, как изначально формировался запрос. В устаревших примерах кода заголовки запроса часто передаются в виде единой текстовой строки, где пары «Ключ: Значение» разделяются символами переноса строк Символы.ВК + Символы.ПС:


// Некорректный подход к формированию заголовков строкой
ЗаголовкиСтрокой = "Accept: text/html" + Символы.ВК + Символы.ПС +
                   "Referer: http://example.com/page.html" + Символы.ВК + Символы.ПС +
                   "Connection: keep-alive";

HTTPСоединение = Новый HTTPСоединение("example.com");
HTTPСоединение.Получить("/dir/file.ext", ИмяФайла, ЗаголовкиСтрокой);

При передаче заголовков строкой встроенный парсер платформы 1С разбивает текст по парам, ориентируясь на символы переноса строк и первое найденное двоеточие. Когда в значении заголовка Referer встречается строка http://, дополнительное двоеточие и слэши сбивают алгоритм текстового разбора платформы. В результате 1С не может корректно разобрать третьей параметр метода Получить и выдает ошибку.

Решение: передача заголовков через объект Соответствие

Для исключения ошибок парсинга передавайте заголовки HTTP-запроса не строкой, а специализированным объектом Соответствие. В этом случае ключевые пары четко разделены на уровне структуры данных 1С, и платформа не выполняет опасную текстовую интерпретацию.

Разберем по шагам правильный алгоритм формирования запроса:

  1. Создаем новый объект Соответствие.
  2. Заполняем заголовки методом Вставить("ИмяЗаголовка", "ЗначениеЗаголовка").
  3. Передаем полученный объект в третий параметр метода Получить или Записать объекта HTTPСоединение.

Посмотрим на пример правильной реализации:


// Формируем структуры заголовков через объект Соответствие
ЗаголовкиЗапроса = Новый Соответствие;
ЗаголовкиЗапроса.Вставить("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
ЗаголовкиЗапроса.Вставить("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3");
ЗаголовкиЗапроса.Вставить("Referer", "http://example.com/dir/page.jsp");
ЗаголовкиЗапроса.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

Сервер = "stupid.com";
ПутьНаСервере = "/dir/file.jsp";
ИмяВременногоФайла = ПолучитьИмяВременногоФайла();

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

Использование Соответствие полностью решает проблему с передачей двоеточий, слэшей и других спецсимволов в значении Referer.

Время жизни HTTP-соединения и сессии

У разработчиков часто возникает вопрос: закрывается ли сетевое соединение с сервером сразу после выполнения метода Получить или держится открытым?

Ответ заключается в следующем: TCP-соединение с веб-сервером удерживается открытым всё то время, пока активна переменная, содержащая объект HTTPСоединение. Автоматическое закрытие сокета происходит в момент очистки переменной или при выходе из области видимости (например, при завершении работы процедуры). Для явного освобождения ресурсов переменной можно присвоить неопределенное значение:

Соединение = Неопределено;

Важные технические нюансы при скачивании файлов по HTTP

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

  1. Заголовок Accept-Encoding: Не передавайте заголовок Accept-Encoding: gzip, deflate вручную при сохранении ответа напрямую в файл через объект HTTPСоединение. Если сервер вернет сжатый поток данных, платформа 8.2 не распакует его автоматически, и в итоговый файл закроется сжатый бинарный архив, который система может посчитать поврежденным.
  2. Перенаправления (HTTP-коды 301 / 302 / 307): Если целевой файл при запросе перенаправляет клиент на другой адрес, старые версии платформы могут не пересылать пользовательские заголовки (включая Referer) на новый URL. В таком случае требуется сначала проанализировать заголовок Location из ответа и выполнить повторный запрос по новому URL.
  3. Использование объектов HTTPЗапрос и HTTPОтвет (для платформы 8.2.18 и новее): В более свежих релизах платформы рекомендуется использовать объектную модель запросов. Это повышает наглядность кода и упрощает работу с заголовками и телом запроса:
    
    Заголовки = Новый Соответствие;
    Заголовки.Вставить("Referer", "http://example.com/page");
    
    Запрос = Новый HTTPЗапрос("/dir/file.jsp", Заголовки);
    Соединение = Новый HTTPСоединение("stupid.com");
    Ответ = Соединение.Получить(Запрос, ИмяВременногоФайла);
    
  4. Альтернатива через WinHTTP (COM-объект): Если штатные средства платформы ведут себя некорректно из-за специфических настроек безопасности сервера, задачу скачивания файла с передачей Referer можно решить через системный COM-объект Windows:
    
    HTTP = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
    HTTP.Open("GET", "http://stupid.com/dir/file.jsp", Ложь);
    HTTP.SetRequestHeader("Referer", "http://example.com/page");
    HTTP.Send();
    
    Если HTTP.Status = 200 Тогда
        Stream = Новый COMОбъект("ADODB.Stream");
        Stream.Type = 1; // Binary
        Stream.Open();
        Stream.Write(HTTP.ResponseBody);
        Stream.SaveToFile(ИмяВременногоФайла, 2);
        Stream.Close();
    КонецЕсли;
    

Таким образом, использование объекта Соответствие является наилучшей практикой для формирования HTTP-заголовков в 1С, так как исключает синтаксические ошибки платформы при парсинге сложных значений URL.

← На главную