При интеграции 1С с современными внешними веб-сервисами (API) разработчики часто сталкиваются с необходимостью авторизации по протоколу HTTPS с использованием токенов безопасности (в частности, Bearer-токенов). На этапе тестирования запросов в специализированных инструментах, таких как Postman, всё работает корректно, однако при переносе логики в код 1С могут возникать непредвиденные трудности. Одной из типичных проблем является внезапный сбой обмена с возвратом HTTP-статуса 307 Temporary Redirect.
В этой статье мы подробно разберем, как правильно реализовать подключение к API с передачей токена в 1С, выясним технические причины возникновения ошибки 307 и рассмотрим надежные способы ее устранения.
Большинство современных REST API используют заголовок Authorization с типом авторизации Bearer. Это означает, что для каждого запроса к защищенному ресурсу сервер ожидает получить строковый ключ (токен) в заголовках пакета.
Рассмотрим стандартный шаблон формирования такого запроса в 1С. Для отправки данных мы будем использовать встроенные объекты платформы: HTTPСоединение и HTTPЗапрос.
Давайте проанализируем пример кода, выполняющего отправку POST-запроса с JSON-телом и Bearer-авторизацией:
// Определим параметры подключения и авторизации
АдресСервера = "api.yourservice.com";
РесурсПуть = "/v1/orders";
ТокенДоступа = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // Пример JWT-токена
// Создаем HTTP-соединение. Пока без параметров шифрования.
HTTPСоединение = Новый HTTPСоединение(АдресСервера);
// Подготавливаем HTTP-запрос
HTTPЗапрос = Новый HTTPЗапрос();
HTTPЗапрос.АдресРесурса = РесурсПуть;
// Добавляем обязательные заголовки
HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer " + ТокенДоступа);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
// Формируем тело запроса (в данном случае отправляем файл JSON)
ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("json");
// Код заполнения файла JSON...
HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
// Инициируем отправку запроса
ИмяФайлаОтвета = ПолучитьИмяВременногоФайла("json");
Попытка
HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос, ИмяФайлаОтвета);
// Обработка успешного ответа сервера
Исключение
ЗаписатьЛогОшибки(ИнформацияОбОшибке().Описание);
КонецПопытки;
В данном примере ключевым моментом является строка добавления заголовка Authorization. Обратите внимание на обязательное наличие пробела после слова Bearer перед склейкой со строкой токена.
Представим ситуацию: ваш интеграционный код успешно работал на протяжении нескольких недель, но в один момент перестал функционировать, а сервер начал возвращать код состояния 307. Что это означает и почему происходит сбой?
Код состояния 307 Temporary Redirect (Временное перенаправление) указывает на то, что запрашиваемый ресурс временно перенесен на другой адрес (URI), указанный в заголовке ответа Location. Главная особенность этого статуса заключается в том, что клиент при повторном запросе к новому адресу **не имеет права изменять метод запроса** (например, заменять POST на GET). Тело исходного запроса должно быть отправлено повторно.
В контексте веб-сервисов 1С наиболее частая причина возникновения редиректа 307 — это **принудительное перенаправление со стандартного протокола HTTP на защищенный HTTPS**. Веб-сервис, к которому вы обращаетесь, перешел на обязательное использование SSL/TLS-шифрования.
Если в коде 1С объект HTTPСоединение инициализирован без явного указания защищенного соединения, платформа пытается отправить запрос по незащищенному порту 80 (HTTP). Веб-сервер перехватывает его и возвращает статус 307 вместе с новым защищенным адресом (начинающимся с https://). Сама платформа 1С по соображениям безопасности не производит автоматический редирект для запросов, содержащих тело данных (POST/PUT), в результате чего выполнение интеграции прерывается с ошибкой.
Для того чтобы избежать промежуточных ренаправлений (редиректов) и сразу адресовать запрос на защищенный порт сервера (443), необходимо явно объявить использование защищенного соединения при инициализации объекта HTTPСоединение.
Для реализации защищенного соединения в платформе 1С предусмотрен специализированный объект ЗащищенноеСоединениеOpenSSL. Давайте посмотрим, как изменится наш код инициализации соединения:
// Создаем объект защищенного соединения OpenSSL.
// По умолчанию используются системные сертификаты операционной системы.
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
// Инициализируем соединение с явным указанием защищенного протокола
// Порт 443 подставится автоматически, так как передано защищенное соединение
HTTPСоединение = Новый HTTPСоединение(
АдресСервера, // Сервер
, // Порт (не указываем, определится автоматически)
, // Пользователь
, // Пароль
, // Прокси
, // Таймаут
ЗащищенноеСоединение // Защищенное соединение OpenSSL
);
Добавление всего одной строки с объявлением ЗащищенноеСоединениеOpenSSL заставляет 1С отправлять шифрованные запросы по протоколу HTTPS. Сервер мгновенно принимает запрос без возврата статуса 307 Redirect, и логика обмена восстанавливается.
Простое создание объекта ЗащищенноеСоединениеOpenSSL() без передачи параметров отлично функционирует на серверах и рабочих станциях под управлением Windows. Это связано с тем, что платформа 1С обращается к встроенному хранилищу сертификатов Windows для подтверждения доверия к центру сертификации (CA) веб-сервиса.
Однако, если ваш сервер приложений 1С развернут на операционной системе **Linux**, могут возникнуть сложности. Серверная платформа 1С на Linux не имеет прямого доступа к централизованному системному хранилищу сертификатов. Вместо этого используется локальный файл-хранилище доверенных сертификатов — cacert.pem, поставляемый вместе с платформой (находится в директории установленной платформы, например: /opt/1cv8/x86_64/[версия_платформы]/bin/cacert.pem).
Если сертификат вашего API выпущен современным или локальным некоммерческим удостоверяющим центром (например, Let's Encrypt или Минцифры РФ), которого нет в стандартной поставке файла cacert.pem, 1С выдаст ошибку рукопожатия SSL (Handshake Error). Для исправления этой ситуации выполните следующие действия:
.crt или .pem).-----BEGIN CERTIFICATE----- и заканчивающиеся на -----END CERTIFICATE-----).cacert.pem на сервере 1С под управлением Linux.cacert.pem и сохраните изменения.В завершение разберем комплексный, отказоустойчивый пример отправки запроса, который включает инициализацию SSL-соединения, установку Bearer-токена в заголовках, чтение тела ответа и обработку потенциальных исключений:
Функция ВыполнитьЗапросКСервису(АдресСервера, ПутьКРесурсу, ТокенАвторизации, ДанныеЗапросаJSON) Экспорт
РезультатВыполнения = Новый Структура("Успех, КодСостояния, Ответ");
РезультатВыполнения.Успех = Ложь;
// Создаем объект SSL-защиты
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
// Инициализируем защищенное HTTPS-соединение
Попытка
HTTPСоединение = Новый HTTPСоединение(
АдресСервера,
443, // Явно указываем стандартный порт HTTPS
, , , 30, // Таймаут 30 секунд
ЗащищенноеСоединение
);
Исключение
РезультатВыполнения.Ответ = "Не удалось установить соединение с сервером: " + ОписаниеОшибки();
Возврат РезультатВыполнения;
КонецПопытки;
// Формируем запрос
HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);
HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer " + ТокенАвторизации);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(ДанныеЗапросаJSON, КодировкаТекста.UTF8, ИспользованиеМаркераПоследовательностиБайтов.НеИспользовать);
// Отправляем запрос и получаем ответ сервера
Попытка
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
РезультатВыполнения.КодСостояния = HTTPОтвет.КодСостояния;
РезультатВыполнения.Ответ = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Если HTTPОтвет.КодСостояния = 200 Или HTTPОтвет.КодСостояния = 201 Тогда
РезультатВыполнения.Успех = Истина;
ИначеЕсли HTTPОтвет.КодСостояния = 307 Тогда
// Извлекаем адрес перенаправления, если это необходимо обработать программно
АдресПеренаправления = HTTPОтвет.Заголовки.Получить("Location");
РезультатВыполнения.Ответ = "Сервер запросил временное перенаправление на адрес: " + АдресПеренаправления;
Иначе
РезультатВыполнения.Ответ = "Сервер вернул ошибку: " + HTTPОтвет.КодСостояния + ". Ответ: " + РезультатВыполнения.Ответ;
КонецЕсли;
Исключение
РезультатВыполнения.Ответ = "Сбой при передаче данных: " + ОписаниеОшибки();
КонецПопытки;
Возврат РезультатВыполнения;
КонецФункции
Использование предложенного шаблона гарантирует корректную работу интеграционных механизмов вашей системы, защищает от непредвиденных изменений сетевых протоколов на стороне веб-сервисов и значительно облегчает отладку при возникновении неполадок.