При интеграции систем 1С:Предприятие с внешними веб-сервисами по протоколу SOAP программисты часто сталкиваются с неочевидным поведением сервера. Ошибки с кодами 301 Moved Permanently и 500 Internal Server Error могут поставить в тупик, так как их причины кроются как в настройках самого соединения, так и в структуре передаваемого XML-пакета. В этой статье мы подробно разберем, как правильно настроить HTTPСоединение, сформировать заголовки и тело запроса, чтобы успешно передать данные.
Ошибка с кодом 301 означает, что запрашиваемый ресурс был окончательно перемещен на другой адрес. В контексте работы с 1С и веб-серверами (например, под управлением nginx) это чаще всего происходит из-за отсутствия завершающего слеша в пути запроса.
Проанализируем ситуацию: если вы указываете путь /api/soap, сервер может автоматически перенаправлять вас на /api/soap/. Рассмотрим, как это выглядит в коде 1С, который вызывает проблему:
HTTPЗапрос = Новый HTTPЗапрос("/api/soap", ЗаголовокЗапросаHTTP);
В этом случае 1С получает ответ с кодом 301. Важно понимать, что объект HTTPСоединение в 1С при использовании метода Получить() или ОтправитьДляОбработки() не всегда автоматически следует за редиректом, особенно если это касается безопасности или изменения типа запроса. Чтобы исправить это, достаточно внимательно изучить заголовок Location в ответе сервера. Если там указан адрес с закрывающим слешем, необходимо просто поправить строку пути в вашем HTTPЗапрос.
Исправленный вариант будет выглядеть так:
HTTPЗапрос = Новый HTTPЗапрос("/api/soap/", ЗаголовокЗапросаHTTP);
Протокол SOAP требует использования метода POST. Часто разработчики на этапе отладки пытаются вызвать HTTPСоединение.Получить(HTTPЗапрос), что соответствует методу GET. Сервер в ответ на это может выдать ошибку RequestNotAllowed или потребовать правильный Content-Type.
Для корректной работы SOAP необходимо использовать метод ОтправитьДляОбработки(). Также критически важно правильно заполнить коллекцию Соответствие для заголовков запроса. Основным заголовком для SOAP 1.1 является Content-Type со значением text/xml; charset=utf-8. Однако многие современные системы, такие как Verme WFM, также требуют специфический заголовок SOAPAction.
Рассмотрим пример настройки заголовков:
ЗаголовокЗапросаHTTP = Новый Соответствие;
ЗаголовокЗапросаHTTP.Вставить("Content-Type", "text/xml; charset=utf-8");
// Для SOAP 1.1 обязательно указываем имя вызываемого метода
ЗаголовокЗапросаHTTP.Вставить("SOAPAction", "setEmployee");
Когда проблема с редиректом решена, может возникнуть ошибка 500 Internal Server Error. Это "общая" ошибка сервера, которая в случае с SOAP почти всегда означает, что сервер не смог распарсить ваш XML или переданные данные не прошли валидацию.
Проанализируем типичные ошибки при ручной сборке XML-строки. В 1С часто используют конкатенацию строк, что чревато незакрытыми тегами или наличием спецсимволов в данных. Посмотрим на пример структуры SOAP Envelope:
СтрокаXML = "
|<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:v1=""http://verme.ru/api/v1"">
| <soapenv:Header/>
| <soapenv:Body>
| <v1:setEmployee>
| <login>" + Логин + "</login>
| <password>" + Пароль + "</password>
| <employee>
| <employeeId>" + employeeId + "</employeeId>
| <name>" + name + "</name>
| </employee>
| </v1:setEmployee>
| </soapenv:Body>
|</soapenv:Envelope>";
Важные моменты при формировании XML:
<soapenv:Envelope>) имеет соответствующий закрывающий тег. В коде из первого сообщения темы была закомментирована строка, что привело к нарушению структуры XML.name или jobcode встретятся символы амперсанда (&), кавычек или скобок, XML станет невалидным. Профессиональнее использовать объект ЗаписьXML для автоматического экранирования.YYYY-MM-DD или YYYY-MM-DDTHH:MM:SS в зависимости от требований WSDL.Если сервер работает по протоколу HTTPS, необходимо инициализировать объект ЗащищенноеСоединениеOpenSSL. Без этого 1С не сможет установить рукопожатие (handshake) с сервером, использующим современные сертификаты. В параметрах конструктора HTTPСоединение этот объект передается последним.
Соединение = Новый HTTPСоединение(
"ekonika-test.verme.ru", // Хост
443, // Порт для HTTPS
Логин,
Пароль,
,
60,
Новый ЗащищенноеСоединениеOpenSSL()
);
Если вы исправили адрес и заголовки, но сервер продолжает возвращать ошибку 500, воспользуйтесь следующими инструментами:
soapenv:Fault). Всегда анализируйте результат методом Результат.ПолучитьТелоКакСтроку(). Там может быть прямо указано, какой параметр передан неверно.Проанализировав ситуацию с редиректами и форматом XML, мы выяснили, что ключ к успеху кроется в точном соблюдении спецификации сервера: правильный путь со слешем, наличие SOAPAction и валидный XML без синтаксических ошибок. Рассмотрим эти рекомендации как обязательный чек-лист при любой интеграции через HTTPСоединение.