При интеграции 1С с внешними веб-сайтами и сервисами часто возникает необходимость перенести готовую команду вызова консольной утилиты cURL в код платформы 1С:Предприятие. Типичный пример такой задачи — отправка данных формы авторизации (логина и пароля) методом POST для получения рабочей сессии. Разберем типичные ошибки, возникающие при переносе команды, и пошагово построим корректный рабочий алгоритм.
Рассмотрим исходную команду cURL, которую требуется перенести в код 1С:
curl -c cookie.txt -d "AuthPhase=1&AUTH_USER=ЛОГИН&AUTH_PW=ПАРОЛЬ" http://b2b.resurs-media.ru/netcat/modules/auth/
Ключ -d указывает на передачу данных в теле HTTP-запроса методом POST в формате веб-формы, а ключ -c предписывает сохранить сессионные куки в файл. При попытке воспроизвести этот вызов разработчики нередко допускают сразу несколько принципиальных ошибок:
HTTPСоединение: параметры конструктора предназначены строго для HTTP Basic или Digest аутентификации на уровне веб-сервера. Если форма авторизации расположена на самом сайте, передача этих параметров сформирует лишний заголовок Authorization, который веб-сервер проигнорирует или вернет ошибку.Соответствие для заголовков (например, Заголовки.Вставить("AUTH_USER", ...)), из-за чего сервер не видит данных в теле POST-запроса и возвращает обратно исходную страницу входа.Content-Type: сервер ожидает данные формы и не может распарсить тело запроса, если тип содержимого не объявлен явно как application/x-www-form-urlencoded.Разберем по шагам правильное формирование HTTP-запроса средствами платформы 1С:
HTTPСоединение без указания пользователя и пароля в конструкторе, передавая только имя хоста и порт.Параметр1=Значение1&Параметр2=Значение2. Значения параметров при необходимости кодируем через КодироватьСтроку().Content-Type со значением application/x-www-form-urlencoded.HTTPЗапрос.УстановитьТелоИзСтроки().ОтправитьДляОбработки() объекта HTTPСоединение.Посмотрим на пример базовой реализации авторизации:
Сервер = "b2b.resurs-media.ru";
ПутьКРесурсу = "/netcat/modules/auth/";
// Инициализируем соединение без указания учетных данных в конструкторе
Соединение = Новый HTTPСоединение(Сервер);
// Заполняем обязательные заголовки
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
// Формируем тело запроса
ДанныеPOST = "AuthPhase=1&AUTH_USER=" + ЛогинПользователя + "&AUTH_PW=" + ПарольПользователя;
// Создаем запрос и помещаем данные в тело
HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу, Заголовки);
HTTPЗапрос.УстановитьТелоИзСтроки(ДанныеPOST, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
// Отправляем POST-запрос на сервер
HTTPОтвет = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
КодСостояния = HTTPОтвет.КодСостояния;
Обратим внимание на метод УстановитьТелоИзСтроки(): по умолчанию платформа использует кодировку UTF-8. Если целевой сайт работает в однобайтовой кодировке (например, Windows-1251), ее необходимо явно указать вторым параметром метода, а также дополнить заголовок: application/x-www-form-urlencoded; charset=windows-1251.
В отличие от утилиты cURL с ключами -c и -b, платформа 1С штатно не ведет автоматическое хранилище cookie-файлов (Cookie Jar). Многие веб-ресурсы требуют сначала выполнить предварительный GET-запрос для получения идентификатора сессии (например, sid или PHPSESSID), и лишь затем отправлять POST-запрос с данными авторизации.
Рассмотрим подробнее сценарий с двухэтапной авторизацией:
Получить() для инициализации сессии на сервере.HTTPОтвет.Заголовки и извлекаем значение по ключу Set-Cookie.path, domain, HttpOnly, expires) и формируем строку для заголовка Cookie.Cookie во второй запрос вместе с POST-параметрами.Проанализируем пример кода с получением и передачей сессионного cookie:
Сервер = "b2b.resurs-media.ru";
ПутьКРесурсу = "/netcat/modules/auth/";
Соединение = Новый HTTPСоединение(Сервер);
// Шаг 1: Первичный GET-запрос для получения cookie
ПервичныйЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);
ПервичныйОтвет = Соединение.Получить(ПервичныйЗапрос);
Куки = "";
Если ПервичныйОтвет.Заголовки.Получить("Set-Cookie") <> Неопределено Тогда
Куки = ПервичныйОтвет.Заголовки.Получить("Set-Cookie");
КонецЕсли;
// Шаг 2: Подготовка POST-запроса с авторизационными данными и сессией
ЗаголовкиPOST = Новый Соответствие;
ЗаголовкиPOST.Вставить("Content-Type", "application/x-www-form-urlencoded");
Если ЗначениеЗаполнено(Куки) Тогда
ЗаголовкиPOST.Вставить("Cookie", Куки);
КонецЕсли;
ДанныеФормы = "AuthPhase=1&AUTH_USER=" + ЛогинПользователя + "&AUTH_PW=" + ПарольПользователя;
АвторизационныйЗапрос = Новый HTTPЗапрос(ПутьКРесурсу, ЗаголовкиPOST);
АвторизационныйЗапрос.УстановитьТелоИзСтроки(ДанныеФормы);
// Шаг 3: Выполнение авторизации
ИтоговыйОтвет = Соединение.ОтправитьДляОбработки(АвторизационныйЗапрос);
После успешной проверки учетных данных большинство веб-систем возвращают не саму защищенную страницу, а HTTP-статусы перенаправления 302 Found или 303 See Other. Объект HTTPСоединение не переходит по редиректам автоматически с сохранением cookie. В таком случае алгоритм действий следующий:
HTTPОтвет.КодСостояния. Если код равен 301, 302 или 303 — авторизация прошла успешно.Location.Set-Cookie текущего ответа.Cookie.Если сервер продолжает возвращать ошибку или страницу авторизации, выясним причину с помощью средств анализа трафика. Наиболее эффективный подход — записать успешный запрос браузера или cURL и сравнить его с запросом из 1С с помощью сниффера (например, Fiddler) или инструментов разработчика в браузере (вкладка Network):
User-Agent, Host или Referer.&, =, +, % или пробелы, их необходимо закодировать вызовом КодироватьСтроку(Пароль, СпособКодированияСтроки.КодировкаURL).WinHttp.WinHttpRequest.5.1, который умеет сохранять сессионные куки и прозрачно следовать за редиректами в автоматическом режиме.