При организации обмена данными между устаревшими и современными системами часто возникают труднообъяснимые ошибки. Одной из таких классических проблем, для отладки которой удобно использовать инструменты вроде Postman для 1С, является ситуация, когда запрос из 1С:Предприятие 7.7 успешно доходит до HTTP-сервиса 1С:Предприятие 8.3, метод вызывается, параметры URL считываются, но тело запроса (body) оказывается абсолютно пустым. Особенно часто это проявляется при переносе решения с файловой базы (под управлением Apache) на серверную (под управлением IIS).
В этой статье мы подробно разберем причины такого поведения и пошагово реализуем механизмы, которые гарантируют доставку данных вне зависимости от используемого веб-сервера.
Рассмотрим ситуацию: на домашнем компьютере с Apache все работает отлично, а у клиента на Windows Server 2008 с IIS данные «теряются». Проанализируем техническую разницу между этими веб-серверами. Apache по умолчанию более лоялен к структуре HTTP-запроса, в то время как IIS (Internet Information Services) строго следует протоколам. Если веб-сервер IIS не получает четкого указания о типе контента или его длине, он может попросту не передать поток данных расширению 1С, считая запрос некорректным или завершенным.
Основные причины проблемы:
Content-Type в запросе из 7.7.WinHttp, когда первый запрос уходит пустым для проверки прав (401 Unauthorized).Для начала проанализируем код отправки. В 1С 7.7 часто забывают про установку заголовков, полагаясь на автоматику (хотя для этих задач существуют и специализированные внешние компоненты). Однако для IIS крайне важно явно указать, что именно мы передаем. Если мы отправляем JSON, сервер должен об этом знать.
Добавим установку заголовка Content-Type. Это позволит IIS правильно идентифицировать входящий поток данных:
WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("POST", URL, 0);
// Указываем тип контента и кодировку
WinHttp.SetRequestHeader("Content-Type", "application/json; charset=utf-8");
WinHttp.SetCredentials(Логин, Пароль, 0);
Также полезно явно указывать заголовок Content-Length, хотя WinHttp обычно вычисляет его автоматически. Однако при работе с прокси-серверами или сложными конфигурациями IIS это может стать решающим фактором.
Это самый важный этап. 1С 7.7 — это ANSI-приложение. Когда мы пишем WinHttp.Send(ПакетJSON), передается строка в кодировке Windows-1251. На стороне 1С 8.3 метод Запрос.ПолучитьТелоКакСтроку() по умолчанию пытается интерпретировать данные как UTF-8. Если в строке встречаются кириллические символы, декодирование завершается ошибкой, и платформа возвращает пустую строку.
Для решения этой задачи воспользуемся объектом ADODB.Stream, чтобы принудительно конвертировать строку в массив байтов UTF-8 перед отправкой. Рассмотрим пример функции преобразования:
// Функция для преобразования строки в UTF-8
Функция ПреобразоватьВUTF8(Текст)
Стрим = СоздатьОбъект("ADODB.Stream");
Стрим.Type = 2; // adTypeText
Стрим.Charset = "utf-8";
Стрим.Open();
Стрим.WriteText(Текст);
Стрим.Position = 0;
Стрим.Type = 1; // adTypeBinary
// Возвращаем двоичные данные
Результат = Стрим.Read();
Возврат Результат;
КонецФункции
Теперь в основном коде отправки вместо передачи текста напрямую, мы будем передавать результат этой функции:
ДанныеДляОтправки = ПреобразоватьВUTF8(ПакетJSON);
WinHttp.Send(ДанныеДляОтправки);
При использовании метода SetCredentials объект WinHttp ведет себя специфически: он сначала отправляет «пустой» запрос без тела, чтобы получить от сервера ответ 401 и тип поддерживаемой авторизации (например, NTLM или Basic). После этого он отправляет запрос повторно уже с данными и заголовком авторизации. В некоторых конфигурациях IIS на серверных ОС (Windows Server 2008/2012) этот процесс может прерываться, особенно при использовании кириллицы в учетных данных.
Проанализируем настройку опций объекта. Мы можем разрешить автоматический редирект и обработку авторизации, установив соответствующие флаги:
WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
// Опция 6 = WinHttpRequestOption_EnableRedirects
WinHttp.Option(6) = 1;
WinHttp.Open("POST", URL, 0);
Если программные методы не помогают, стоит заглянуть в настройки веб-сервера. В IIS существует модуль Request Filtering, который может блокировать тела запросов, если они превышают определенный размер, или если тип контента не разрешен.
Разберем, что нужно проверить в файле web.config, который находится в папке публикации вашей базы 1С:
requestFiltering.maxAllowedContentLength. Он определяет максимальный размер запроса в байтах.Пример правильной настройки в web.config:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="104857600" />
</requestFiltering>
</security>
</system.webServer>
Здесь мы установили лимит в 100 Мб, что гарантирует прохождение даже больших JSON-пакетов.
На стороне приемника (8.3) также рекомендуется внести небольшие изменения для диагностики. Вместо метода Запрос.ПолучитьТелоКакСтроку() попробуйте сначала считать двоичные данные. Это позволит понять: данные не пришли вовсе или они пришли в «кривой» кодировке.
Проанализируем пример отладочного кода в 8.3:
Функция ОбслуживаниеЗапроса(Запрос)
// Проверяем наличие данных в принципе
ДвоичныеДанные = Запрос.ПолучитьТелоКакДвоичныеДанные();
РазмерДанных = ДвоичныеДанные.Размер(); // Если > 0, значит данные дошли
// Пытаемся прочитать как строку, явно указав кодировку
СтрокаJSON = Запрос.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
// Если СтрокаJSON пустая, но РазмерДанных > 0 - проблема в кодировке!
КонецФункции
Важный совет: В конфигураторе 1С 8.3 для метода HTTP-сервиса вместо значения «Любой» (Any) в поле «HTTP метод» лучше явно выбрать «POST». IIS корректнее сопоставляет обработчики, когда метод определен однозначно.
Чтобы данные из 1С 7.7 стабильно попадали в 1С 8.3 под управлением IIS, необходимо:
Content-Type: application/json; charset=utf-8.ADODB.Stream.maxAllowedContentLength в web.config на сервере.Следуя этим шагам, мы обеспечим надежную работу интеграции и исключим потерю данных при передаче между разными поколениями платформы 1С.