Разработка HTTP-сервисов в системе «1С:Предприятие» — это мощный инструмент для интеграции, однако он накладывает жесткие требования к чистоте серверного кода. Часто разработчики сталкиваются с ситуацией, когда при выполнении безобидной строки кода Объект = Документы.РеализацияТоваровУслуг.СоздатьДокумент(); сервис внезапно «падает», возвращая стандартный ответ HTTP 500 (Internal Server Error). При этом отладка может обрываться в самом конце модуля объекта, а журнал регистрации не фиксирует никаких ошибок. Разберем подробно, почему это происходит и как решить проблему кардинально.
Первое, что мы должны четко понимать: HTTP-сервисы всегда выполняются исключительно в контексте сервера. В отличие от тонкого или толстого клиента, здесь нет интерфейса, нет возможности вывести сообщение пользователю и нет доступа к клиентским процедурам. Более того, контекст HTTP-сервиса отличается от привычного нам контекста «Внешнего соединения» (COM). Если во внешнем соединении активен признак ВнешнееСоединение, то в HTTP-сервисе работает только признак Сервер.
Проанализируем пример кода, который помогает точно определить, в какой области выполняется наш сервис:
// Проверка контекста выполнения
#Если Клиент Тогда
Контекст = "Клиент";
#ИначеЕсли НаКлиенте Тогда
Контекст = "НаКлиенте";
#ИначеЕсли Сервер Тогда
Контекст = "Сервер";
#ИначеЕсли ВнешнееСоединение Тогда
Контекст = "ВнешнееСоединение";
#КонецЕсли
Практика показывает, что при работе через HTTP-сервис платформа однозначно идентифицирует сеанс как Сервер. Это означает, что любые попытки обратиться к методам, доступным только в клиенте, приведут к мгновенному завершению рабочего процесса или сбою сеанса.
На первый взгляд кажется странным, что вызов метода СоздатьДокумент() приводит к падению, если в самом обработчике HTTP-запроса кода почти нет. Однако в 1С процесс создания объекта запускает цепную реакцию инициализаций:
УстановкаПараметровСеанса. Если в ней есть ошибки или обращения к глобальным переменным клиентского приложения, сеанс будет нестабилен.Сервер и Глобальный. Если в разделе описания переменных такого модуля или в его теле (вне процедур) есть код, вызывающий клиентские функции, сервис упадет.СоздатьДокумент() инициализирует модуль объекта создаваемого документа. Если в старых конфигурациях (например, БП 1.6) в модуле объекта прописаны вызовы процедур из клиентских общих модулей или обращение к ГлобальномуКонтексту обычного приложения, возникнет исключение.Рассмотрим ситуацию: отладчик доходит до последней строки модуля объекта и после этого возвращает ошибку 500. Это верный признак того, что ошибка происходит в момент завершения инициализации объекта, когда система пытается «подтянуть» зависимости, не прошедшие проверку на серверный контекст.
Чтобы решить проблему падения сервиса, необходимо выполнить полную ревизию кода на предмет серверной совместимости. Проанализируем основные шаги:
Воспользуйтесь встроенным механизмом проверки конфигурации. Откройте конфигуратор, выберите меню «Конфигурация — Проверка конфигурации». В настройках обязательно установите галочку «Сервер» и снимите галочки со всех клиентских режимов. Запустите проверку. Все найденные ошибки вида «Процедура или функция не определена» в контексте сервера — это потенциальные причины ошибки 500.
Любые вызовы диалоговых окон, сообщений пользователю или методов работы с интерфейсом должны быть обернуты в инструкции препроцессора. Рассмотрим пример правильного оформления кода в общем модуле, который используется и в интерфейсе, и в сервисах:
Процедура РассчитатьПараметрыДокумента(ДокументОбъект) Экспорт
// Логика расчета, доступная везде
ДокументОбъект.Сумма = ДокументОбъект.Товары.Итог("Сумма");
#Если Клиент Тогда
// Это сообщение увидит только пользователь в интерфейсе
Сообщить("Расчет завершен успешно!");
#КонецЕсли
КонецПроцедуры
В старых конфигурациях часто используются переменные, объявленные в МодулеОбычногоПриложения. При работе HTTP-сервиса этот модуль не инициализируется. Если ваш код (например, в модуле объекта документа) обращается к таким переменным напрямую, вы получите ошибку. Замените прямые обращения на вызов функций из общих модулей, которые умеют определять контекст и возвращать значения по умолчанию для сервера.
Если журнал регистрации молчит, а отладка не дает ответа, единственным надежным способом остается Технологический журнал (ТЖ). Создайте файл logcfg.xml в каталоге настроек сервера 1С и добавьте отслеживание событий EXCP (исключения). В логах ТЖ вы увидите точный текст ошибки, например: Метод 'Предупреждение' не обнаружен, и стек вызова, который привел к падению.
Часто падение происходит из-за того, что в HTTP-сервисе не заполнены ПараметрыСеанса (например, ТекущийПользователь). При создании документа срабатывает подписка на событие или код в модуле объекта, пытающийся прочитать эти параметры. Проанализируем, как правильно инициализировать их в МодулеСеанса:
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
// Важно: код здесь должен быть абсолютно безопасным для сервера
Если ПараметрыСеанса.ТекущийПользователь.Пустая() Тогда
// Логика определения пользователя для HTTP-сервиса
ПараметрыСеанса.ТекущийПользователь = Справочники.Пользователи.НайтиПоНаименованию("СервисныйПользователь");
КонецЕсли;
КонецПроцедуры
Подводя итог, можно сказать, что ошибка 500 при вызове СоздатьДокумент() — это почти всегда ошибка компиляции или выполнения клиентского кода на сервере. Для исправления ситуации необходимо:
Сервер на наличие клиентских вызовов.Сообщить, Предупреждение, Вопрос и работу с формами в #Если Клиент Тогда.Объект, чтобы избежать конфликтов имен в некоторых контекстах (хотя это вторично).Соблюдение этих правил позволит вашим HTTP-сервисам работать стабильно, а создание документов программным путем не будет вызывать критических сбоев системы.