Работа с внешними системами через стандартный интерфейс OData в 1С — это мощный инструмент интеграции, однако на этапе настройки разработчики часто сталкиваются с техническими препятствиями. Одной из самых распространенных проблем является получение кода состояния 301 Moved Permanently вместо ожидаемого ответа с данными. В этой статье мы подробно разберем, почему возникает эта ошибка, как правильно настроить параметры HTTPСоединение и как корректно передавать данные в базу, включая работу с табличными частями.
Когда при выполнении запроса HTTPСоединение.Получить() или ОтправитьДляОбработки() сервер возвращает код 301, это означает, что ресурс был окончательно перемещен по другому адресу. Проанализируем ситуацию: сервер сообщает клиенту (вашему коду 1С), что запрос нужно повторить, но уже по другому URL. Рассмотрим основные причины, по которым это происходит в контексте 1С:
/ (например, .../standard.odata) перенаправляются на адрес со слешем (.../standard.odata/).localhost часто становится камнем преткновения.Для диагностики первым делом нужно изучить заголовок Location, который приходит в ответе сервера. Разберем пример кода, который поможет увидеть, куда именно сервер пытается нас перенаправить:
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 301 Тогда
НовыйАдрес = Ответ.Заголовки.Получить("Location");
Сообщить("Сервер требует перенаправления на: " + НовыйАдрес);
КонецЕсли;
Важно помнить: объект HTTPСоединение в языке 1С автоматически не следует по пути из Location. Вам необходимо либо исправить исходный адрес в коде, либо программно обработать редирект.
Проанализируем ситуацию, описанную в сообщениях форума: почему обращение к localhost часто приводит к ошибке? Здесь важно понимать разницу между клиентским и серверным контекстом 1С.
Выясним причину: когда вы пишете Сервер = "localhost", это обращение к "самому себе".
Если код выполняется &НаКлиенте, 1С ищет веб-сервер на компьютере пользователя.
Если код выполняется &НаСервере, 1С ищет веб-сервер на той машине, где установлена серверная часть (кластер) 1С.
Если ваша база опубликована на отдельном веб-сервере, отличном от того, где запущен кластер 1С, использование localhost в серверном коде будет ошибкой. Вместо этого необходимо указывать реальный IP-адрес или сетевое имя сервера, на котором произведена публикация. Рассмотрим правильный вариант инициализации соединения:
ПараметрыСоединения = Новый Структура;
// Указываем реальное имя сервера в сети, а не localhost
ПараметрыСоединения.Вставить("Сервер", "192.168.1.10");
ПараметрыСоединения.Вставить("Порт", 80);
ПараметрыСоединения.Вставить("Пользователь", "ODataUser");
ПараметрыСоединения.Вставить("Пароль", "StrongPassword123");
ЗащищенноеСоединение = Неопределено; // Используйте Новый ЗащищенноеСоединениеOpenSSL(), если нужен HTTPS
HTTPСоединение = Новый HTTPСоединение(
ПараметрыСоединения.Сервер,
ПараметрыСоединения.Порт,
ПараметрыСоединения.Пользователь,
ПараметрыСоединения.Пароль,
, ,
ЗащищенноеСоединение
);
Рассмотрим подробнее, как передавать данные для создания новых объектов в базе через OData. Для этого используется метод POST, а данные передаются в теле запроса в формате JSON. Посмотрим на структуру формирования данных для одного документа:
ДанныеДокумента = Новый Соответствие;
// GUID должен быть в формате строки: "00000000-0000-0000-0000-000000000000"
ДанныеДокумента.Вставить("Организация_Key", "d4aff59d-d3a8-11ed-8dfa-10bf48ba43bd");
// Дата передается строго в формате ISO: YYYY-MM-DDTHH:mm:ss
ДанныеДокумента.Вставить("Date", Формат(ТекущаяДатаСеанса(), "ДФ=yyyy-MM-ddTHH:mm:ss"));
ДанныеДокумента.Вставить("Comment", "Создано через OData");
// Преобразование в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДокумента);
СтрокаЗапроса = ЗаписьJSON.Закрыть();
АдресРесурса = "/buh_dev/odata/standard.odata/Document_РеализацияТоваровУслуг";
Запрос = Новый HTTPЗапрос(АдресРесурса);
Запрос.УстановитьТелоИзСтроки(СтрокаЗапроса);
Ответ = HTTPСоединение.ОтправитьДляОбработки(Запрос);
Часто возникает вопрос: как за один запрос передать не только реквизиты шапки, но и строки табличной части? Разберем по шагам этот процесс. В OData 1С табличная часть представляется как массив объектов (структур или соответствий), вложенный в основной объект данных под именем этой табличной части.
Проанализируем пример формирования данных для документа с табличной частью Товары:
ДанныеОбъекта = Новый Соответствие;
ДанныеОбъекта.Вставить("Организация_Key", "GUID-организации");
// Создаем массив для хранения строк табличной части
МассивСтрокТЧ = Новый Массив;
// Формируем первую строку
СтрокаТЧ = Новый Соответствие;
СтрокаТЧ.Вставить("LineNumber", "1");
СтрокаТЧ.Вставить("Номенклатура_Key", "GUID-номенклатуры");
СтрокаТЧ.Вставить("Количество", 10);
СтрокаТЧ.Вставить("Цена", 1500);
МассивСтрокТЧ.Добавить(СтрокаТЧ);
// Добавляем массив строк в основной объект по имени ТЧ
ДанныеОбъекта.Вставить("Товары", МассивСтрокТЧ);
// Сериализуем в JSON и отправляем POST-запрос, как в примере выше
Важный момент: если вы используете метод PATCH для обновления существующего документа, передача табличной части в запросе обычно полностью заменяет (перезаписывает) все существующие строки в базе данными из вашего запроса. Будьте осторожны, чтобы не удалить существующие данные по ошибке.
Хотя стандартные примеры показывают создание одного объекта за раз, OData поддерживает механизм $batch. Это позволяет объединить несколько операций (создание, изменение) в один HTTP-запрос. Это критически важно для производительности, так как накладные расходы на установку HTTP-соединения часто превышают время самой записи данных.
Режим $batch требует формирования сложного тела запроса в формате multipart/mixed. Если вам нужно передать тысячи объектов, стоит изучить этот механизм подробнее в документации к платформе 1С.
Если соединение все равно не устанавливается, проверим настройки самой публикации базы:
default.vrd параметр standardOdata должен быть установлен в значение true.Используя эти рекомендации, вы сможете эффективно настроить взаимодействие с 1С через интерфейс OData, корректно обрабатывая ошибки соединения и правильно структурируя передаваемые данные.