При работе с веб-сервисами (особенно SOAP ASMX) на устаревших платформах семейства 1С:Предприятие 8.1 или ранних релизах 8.2 разработчики регулярно сталкиваются со странным поведением метода ОтправитьДляОбработки(). Наиболее частая проблема — неинформативная ошибка «Ошибка при вызове метода контекста (ОтправитьДляОбработки): Ошибка доступа к файлу».
В этой статье мы подробно разберем, почему возникает эта ошибка, исправим неверную структуру POST-запроса, настроим базовую авторизацию и рассмотрим более надежную альтернативу на основе системных COM-объектов Windows.
В старых версиях платформы 1С встроенный HTTP-клиент работает по упрощенной схеме. Если удаленный веб-сервер при попытке отправить POST-запрос возвращает ошибку авторизации (HTTP 401 Unauthorized), ошибку безопасности (SSL/TLS) или сообщает о неверном формате запроса (HTTP 400 Bad Request), платформа 1С зачастую не может корректно интерпретировать этот статус. Вместо вывода реальной сетевой ошибки она генерирует исключение «Ошибка доступа к файлу '[ИмяРесурса]'».
Таким образом, данная неполадка в 99% случаев указывает не на права в операционной системе, а на одну из следующих сетевых проблем:
Рассмотрим по шагам, как исправить каждую из этих архитектурных ошибок.
Проанализируем типичную ошибку начинающих разработчиков. Попытка записать стартовую строку HTTP-запроса (POST /asup_rus... HTTP/1.1) и заголовки (Content-Type, Content-Length) прямо в файл тела запроса в корне неверна:
// ТАК ДЕЛАТЬ НЕЛЬЗЯ!
ТекстФайл.ДобавитьСтроку("POST /asup_rus/WebServiceLoadDistr/Service_for_otgr.asmx HTTP/1.1");
ТекстФайл.ДобавитьСтроку("Content-Type: text/xml; charset=utf-8");
ТекстФайл.ДобавитьСтроку("Content-Length: length");
ТекстФайл.ДобавитьСтроку(ТекстXML);
При использовании встроенного метода ОтправитьДляОбработки() платформа 1С самостоятельно формирует стартовую строку POST и вычисляет заголовок Content-Length на основании переданного временного файла тела. Если прописать эти данные вручную в тело, веб-сервер получит некорректный XML-пакет и вернет ошибку.
Для корректной передачи заголовков SOAP (таких как Content-Type и SOAPAction) необходимо использовать специальный параметр — объект типа Соответствие. Рассмотрим правильный пример формирования запроса:
// 1. Инициализируем соединение с сервером
Соединение = Новый HTTPСоединение("asup.konti.com");
// 2. Создаем соответствие для HTTP-заголовков
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
// Вместо ИмяМетода укажите реальное действие вашего SOAP-сервиса
Заголовки.Вставить("SOAPAction", "http://tempuri.org/ИмяМетода");
// 3. Формируем временный файл, содержащий ТОЛЬКО чистый XML-код тела запроса
ФайлТелаЗапроса = ПолучитьИмяВременногоФайла();
ТекстФайл = Новый ТекстовыйДокумент;
ТекстФайл.УстановитьТекст(ТекстXML); // Передаем чистый XML без HTTP-заголовков
ТекстФайл.Записать(ФайлТелаЗапроса, КодировкаТекста.UTF8);
ФайлРезультата = ПолучитьИмяВременногоФайла();
// 4. Отправляем запрос, передавая заголовки в качестве 4-го параметра
Попытка
Соединение.ОтправитьДляОбработки(ФайлТелаЗапроса, "/asup_rus/WebServiceLoadDistr/Service_for_otgr.asmx", ФайлРезультата, Заголовки);
Сообщить("Запрос успешно отправлен!");
Исключение
Сообщить("Ошибка при отправке: " + ОписаниеОшибки());
КонецПопытки;
Если веб-сервис требует ввода логина и пароля (базовая авторизация Basic Authentication), передавать эти учетные данные нужно в момент инициализации объекта HTTPСоединение. Платформа автоматически закодирует их по стандарту Base64 и добавит заголовок Authorization к каждому запросу.
Изменим конструктор подключения, задействуя параметры авторизации:
// Синтаксис: Новый HTTPСоединение(Сервер, Порт, Пользователь, Пароль, Прокси, Таймаут)
Логин = "MyWebUser";
Пароль = "MySecretPassword";
Соединение = Новый HTTPСоединение("asup.konti.com", , Логин, Пароль);
Этого достаточно, чтобы обойти ограничение закрытого ресурса без ручного формирования сложных куки-сессий.
Объект HTTPСоединение в старых версиях 1С (особенно в 8.1) имеет критические ограничения: он плохо справляется с перенаправлениями (redirects), не умеет работать по защищенным протоколам TLS 1.2+ и не позволяет гибко анализировать статус HTTP-ответа сервера.
Золотым стандартом для решения подобных интеграционных задач на старых версиях платформы является использование системного COM-объекта Windows — WinHttp.WinHttpRequest.5.1. Он работает напрямую с системными библиотеками Windows, поддерживает современные стандарты безопасности и избавляет от необходимости постоянно генерировать временные файлы на диске.
Проанализируем пример отправки SOAP-запроса через WinHttp:
// 1. Создаем COM-объект запроса
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// 2. Настраиваем опции (кодировка utf-8 и игнорирование ошибок сертификатов)
WinHttp.Option(2, "utf-8");
WinHttp.Option(4, 13056); // Игнорировать SSL-ошибки при необходимости
// 3. Открываем асинхронное/синхронное соединение (Ложь — синхронный режим)
URLРесурса = "http://asup.konti.com/asup_rus/WebServiceLoadDistr/Service_for_otgr.asmx";
WinHttp.Open("POST", URLРесурса, Ложь);
// 4. Задаем необходимые HTTP-заголовки
WinHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
WinHttp.setRequestHeader("SOAPAction", "http://tempuri.org/ИмяМетода");
// 5. Передаем логин и пароль для базовой авторизации
// Третий параметр (0) означает авторизацию непосредственно на целевом сервере HTTP
WinHttp.SetCredentials("MyWebUser", "MySecretPassword", 0);
// 6. Отправляем запрос, передавая XML-текст напрямую без промежуточных файлов
Попытка
WinHttp.Send(ТекстXML);
// Получаем статус ответа от сервера
КодСостояния = WinHttp.Status;
ТекстСтатуса = WinHttp.StatusText;
Если КодСостояния = 200 Тогда
// Запрос выполнен успешно, получаем ответ в виде текста
РезультатОтвета = WinHttp.ResponseText;
Сообщить("Запрос обработан успешно!");
Иначе
Сообщить("Сервер вернул ошибку. Код: " + КодСостояния + " (" + ТекстСтатуса + ")");
КонецЕсли;
Исключение
Сообщить("Не удалось установить связь с веб-сервисом: " + ОписаниеОшибки());
КонецПопытки;
Если вы внесли исправления в код, но веб-сервис по-прежнему возвращает некорректные данные или ошибки соединения, воспользуйтесь специализированным прокси-сервером для анализа трафика, например, Fiddler. Это позволит вам увидеть реальный исходящий пакет из 1С (включая все скрытые заголовки и структуру тела) и сравнить его с эталонным запросом, отправленным, например, из отладочной утилиты Postman.