При интеграции 1С 7.7 с внешними системами часто возникает задача отправки данных, например, в формате XML, на удаленный сервер. В процессе можно столкнуться с различными HTTP-ошибками, одна из которых — 406 Not Acceptable. Давайте разберемся, почему она возникает и какие существуют надежные способы для отправки файлов из старой доброй "семерки".
Проанализируем ситуацию: при попытке отправить XML-файл с помощью POST-запроса сервер возвращает ошибку 406 Not Acceptable. Это означает, что сервер не может предоставить ответ в формате, который запрашивает клиент. Часто разработчики концентрируются на заголовке Content-Type, который описывает отправляемые данные, но корень проблемы может быть в другом.
Основная причина ошибки 406 — несоответствие заголовка Accept в запросе клиента и форматов, которые может отдать сервер. Клиент должен явно указать, какой тип контента он готов принять в ответе. Если этот заголовок не указан или его значение не устраивает сервер, возникает данная ошибка.
Хотя в обсуждаемой проблеме использовалась сторонняя компонента HTTPS77.dll, для которой не нашлось готового примера, существуют другие внешние компоненты для работы по HTTP(S) и более надежные стандартные инструменты, которые прекрасно справляются с этой задачей. Рассмотрим их подробно.
Самый надежный и не требующий установки внешних компонент способ (наряду с использованием библиотек готовых функций для 1С 7.7) — это использование встроенных в Windows COM-объектов. Для работы с HTTP-запросами в 1С 7.7 (например, для загрузки курсов валют) идеально подходят MSXML2.ServerXMLHTTP и WinHTTP.WinHTTPRequest.
Этот объект является частью библиотеки Microsoft XML Core Services и отлично подходит для работы с XML. Он корректно обрабатывает кодировки и позволяет работать с XML-документами напрямую. Важно использовать последнюю доступную версию объекта, например, MSXML2.ServerXMLHTTP.6.0, так как она поддерживает современные протоколы шифрования (TLS 1.2), без которых подключиться к большинству современных серверов не получится.
Посмотрим на пример кода для отправки XML-файла:
// Функция для отправки XML-файла на сервер
// Возвращает текст ответа сервера или описание ошибки
Функция ОтправитьXMLНаСервер(ПутьКФайлу, URL)
// 1. Создаем объект для HTTP-запросов
Попытка
HTTPЗапрос = СоздатьОбъект("MSXML2.ServerXMLHTTP.6.0");
Исключение
Возврат "Не удалось создать объект MSXML2.ServerXMLHTTP.6.0. Проверьте, установлены ли Microsoft Core XML Services 6.0.";
КонецПопытки;
// 2. Создаем и загружаем XML-документ из файла
// Этот шаг необязателен, можно прочитать файл в текстовую переменную
// Но работа через DOM-объект более структурирована
Попытка
XMLДокумент = СоздатьОбъект("MSXML2.DOMDocument.6.0");
XMLДокумент.async = 0; // Устанавливаем синхронный режим загрузки
Если XMLДокумент.load(ПутьКФайлу) = 0 Тогда
Возврат "Ошибка загрузки XML-файла: " + XMLДокумент.parseError.reason;
КонецЕсли;
Исключение
Возврат "Не удалось создать объект MSXML2.DOMDocument.6.0.";
КонецПопытки;
// 3. Открываем соединение методом POST
// Третий параметр (0 или False) означает синхронный режим выполнения
HTTPЗапрос.open("POST", URL, 0);
// 4. Устанавливаем ключевые заголовки запроса
// Сообщаем серверу, что мы отправляем XML в кодировке UTF-8
HTTPЗапрос.setRequestHeader("Content-Type", "application/xml; charset=utf-8");
// Сообщаем серверу, что мы готовы принять ответ в формате XML
// Это ключевой момент для предотвращения ошибки 406 Not Acceptable
HTTPЗапрос.setRequestHeader("Accept", "application/xml");
// 5. Отправляем тело запроса (содержимое XML)
// Метод send может принимать как строку, так и DOM-объект
HTTPЗапрос.send(XMLДокумент);
// 6. Анализируем ответ сервера
Если HTTPЗапрос.status = 200 Тогда // 200 OK - успешное выполнение
Возврат HTTPЗапрос.responseText;
Иначе
Возврат "Ошибка: " + HTTPЗапрос.status + " " + HTTPЗапрос.statusText;
КонецЕсли;
КонецФункции
// Пример вызова функции
Процедура ВыполнитьОтправку()
ПутьКФайлу = "C:\temp\data.xml";
URL = "https://адрес.сервера/api/upload";
Ответ = ОтправитьXMLНаСервер(ПутьКФайлу, URL);
Сообщить(Ответ);
КонецПроцедуры
В этом примере мы по шагам разобрали весь процесс: создали объекты, установили правильные заголовки, отправили данные и обработали результат. Главное внимание здесь стоит уделить строке HTTPЗапрос.setRequestHeader("Accept", "application/xml");, которая и решает проблему с ошибкой 406.
Это еще один мощный COM-объект для работы с HTTP. Он считается более современным и универсальным, чем ServerXMLHTTP, и также отлично поддерживает современные протоколы безопасности. Синтаксис работы с ним очень похож.
cURL — это мощнейшая утилита командной строки для передачи данных по различным протоколам, включая HTTP/HTTPS. Её использование из 1С 7.7 — это отличный способ обойти ограничения старой платформы и COM-объектов, особенно в части поддержки новейших стандартов шифрования.
Для вызова утилиты из 1С 7.7 можно использовать функцию ЗапуститьПриложение() или КомандаСистемы(). Результат работы можно перенаправить в текстовый файл и затем прочитать его средствами 1С.
Рассмотрим пример команды для отправки нашего XML-файла:
curl -X POST -H "Content-Type: application/xml" -H "Accept: application/xml" --data-binary "@C:\temp\data.xml" https://адрес.сервера/api/upload -o C:\temp\response.txt -w "%{http_code}" -s
Разберем эту команду по частям:
-X POST — указывает, что используется метод POST.-H "..." — позволяет задать заголовки запроса. Мы указываем и Content-Type, и Accept.--data-binary "@C:\temp\data.xml" — указывает, что тело запроса нужно взять из файла. Символ @ перед путем означает, что нужно передать содержимое файла, а не сам путь как строку.https://адрес.сервера/api/upload — URL-адрес, на который отправляется запрос.-o C:\temp\response.txt — перенаправляет тело ответа сервера в файл response.txt.-w "%{http_code}" — выводит в стандартный поток вывода (консоль) код ответа HTTP (например, 200 или 404).-s — "тихий" режим, скрывает индикатор прогресса.Чтобы выполнить это из 1С, можно написать следующий код:
Процедура ОтправитьФайлЧерезCurl()
ПутьКФайлу = "C:\temp\data.xml";
ПутьКОтвету = "C:\temp\response.txt";
ПутьКФайлуКода = "C:\temp\http_code.txt";
URL = "https://адрес.сервера/api/upload";
// Формируем команду для выполнения
Команда = "curl -X POST -H ""Content-Type: application/xml"" " +
"-H ""Accept: application/xml"" " +
"--data-binary ""@" + ПутьКФайлу + """ " +
URL + " " +
"-o " + ПутьКОтвету + " " +
"-w ""%{http_code}"" -s > " + ПутьКФайлуКода;
// Запускаем команду и ждем ее завершения
ЗапуститьПриложение(Команда, "", 1);
// Читаем код ответа
Текст = СоздатьОбъект("Текст");
Текст.Открыть(ПутьКФайлуКода);
КодОтвета = Число(Текст.ПолучитьСтроку(1));
Текст.Закрыть();
Если КодОтвета = 200 Тогда
// Читаем тело ответа, если нужно
Текст.Открыть(ПутьКОтвету);
ТелоОтвета = "";
Для i = 1 По Текст.КоличествоСтрок() Цикл
ТелоОтвета = ТелоОтвета + Текст.ПолучитьСтроку(i);
КонецЦикла;
Текст.Закрыть();
Сообщить("Успешно! Ответ сервера: " + ТелоОтвета);
Иначе
Сообщить("Ошибка! HTTP-код: " + КодОтвета);
КонецЕсли;
КонецПроцедуры
Также стоит упомянуть, что для более тесной интеграции cURL и 1С 7.7 существуют готовые внешние компоненты (например, curl1c.dll), которые оборачивают функциональность утилиты в удобные методы 1С, избавляя от необходимости работать с командной строкой и файлами.
Итак, чтобы успешно отправить XML-файл из 1С 7.7 и избежать ошибки 406 Not Acceptable, необходимо:
MSXML2.ServerXMLHTTP.6.0) или мощную внешнюю утилиту (cURL).Content-Type, описывающего тело вашего запроса, не забывайте указывать заголовок Accept, чтобы сообщить серверу, какой формат ответа вы ожидаете (например, application/xml).Выбор между COM-объектом и cURL зависит от задачи. Для простых запросов внутри защищенной сети достаточно COM. Для сложных интеграций с современными веб-сервисами, требующими гибкой настройки и поддержки последних стандартов безопасности, cURL будет более предпочтительным вариантом.