Почему HTTP-сервис 1С открывается в браузере, но выдает ошибку при вызове из кода 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Разработка и отладка HTTP-сервисов в среде 1С:Предприятие часто преподносит сюрпризы. Типичная ситуация: вы написали сервис, опубликовали его на веб-сервере (IIS или Apache), вставили ссылку в адресную строку браузера и получили идеальный JSON. Однако при попытке вызвать этот же сервис из кода 1С с помощью объекта HTTPСоединение, система выдает ошибку выполнения или сообщает о «потенциально опасном значении в пути».

В данной статье мы подробно разберем, почему возникает такая разница в поведении, проанализируем ошибки веб-серверов и научимся правильно формировать запросы в коде 1С.

Анализ ситуации: ошибка Request.Path и символ двоеточия

Рассмотрим первую и самую коварную проблему. При работе через Internet Information Services (IIS) программист может столкнуться со следующим сообщением: [HttpException]: Обнаружено потенциально опасное значение Request.Path, полученное от клиента (:). Выясним причину этого поведения.

Когда мы работаем в браузере, мы вводим полный URL, например: http://myserver/base/hs/service/method. Однако объектная модель 1С требует разделения этого адреса на две части:

  1. Параметры подключения к серверу (имя сервера, порт, протокол), которые передаются в конструктор HTTPСоединение.
  2. Относительный путь к ресурсу, который передается в объект HTTPЗапрос.

Основная ошибка заключается в том, что разработчики часто дублируют протокол или имя сервера в HTTPЗапрос. Если в HTTPЗапрос передать строку, начинающуюся с http://, веб-сервер IIS увидит двоеточие в середине пути запроса. Согласно политикам безопасности ASP.NET, двоеточие считается потенциально опасным символом в Request.Path, что и вызывает немедленную блокировку запроса еще до того, как управление будет передано платформе 1С.

Проанализируем пример неправильного кода:


// ОШИБОЧНЫЙ КОД
Сервер = "192.168.1.10";
ПутьКСервису = "http://192.168.1.10/MyBase/hs/v1/get_data"; // Ошибка здесь!

Соединение = Новый HTTPСоединение(Сервер);
Запрос = Новый HTTPЗапрос(ПутьКСервису); // Передается полный URL с двоеточием
Ответ = Соединение.Получить(Запрос);

Правильный подход требует, чтобы в HTTPЗапрос попадал только путь, начиная от публикации базы (или от корня веб-сервера, если база опубликована в корне):


// ПРАВИЛЬНЫЙ КОД
Сервер = "192.168.1.10";
ОтносительныйПуть = "/MyBase/hs/v1/get_data"; 

Соединение = Новый HTTPСоединение(Сервер);
Запрос = Новый HTTPЗапрос(ОтносительныйПуть); 
Ответ = Соединение.Получить(Запрос);

Разберем влияние настроек веб-сервера (IIS и web.config)

Если специфика вашего сервиса действительно требует передачи специфических символов в строке запроса (например, двоеточий в параметрах времени или специфических меток), можно настроить фильтрацию на стороне IIS. Рассмотрим, как это сделать через файл web.config, который находится в каталоге публикации базы 1С.

Для того чтобы разрешить обработку «опасных» символов, необходимо найти секцию <system.web> и добавить (или отредактировать) параметр httpRuntime:


<configuration>
  <system.web>
    <httpRuntime requestPathInvalidCharacters="" />
  </system.web>
</configuration>

Установка пустого значения в requestPathInvalidCharacters отключает проверку на недопустимые символы. Внимание: это снижает уровень безопасности сервера, поэтому рекомендуется использовать этот метод только в закрытых корпоративных сетях и отдавать предпочтение правильному формированию URL или использованию параметров запроса (URL Parameters) вместо сегментов пути.

Особенности работы с Apache: ошибка 403 и регистр символов

При переходе с IIS на Apache пользователи часто сталкиваются с ошибкой 403 Forbidden или AH00127: Cannot map GET /. Выясним причину, проанализировав лог-файлы Apache.

В отличие от Windows и IIS, сервер Apache (особенно на Linux) крайне чувствителен к регистру символов в URL. Рассмотрим типичные проблемы:

Пример кодирования параметров в 1С:


Функция ПодготовитьПуть(ДатаНачала, ДатаОкончания)
    Шаблон = "/base/hs/attendance_info/%1/%2";
    // Используем кодирование, если в параметрах могут быть спецсимволы
    СтрДата1 = Формат(ДатаНачала, "ДФ=yyyyMMdd");
    СтрДата2 = Формат(ДатаОкончания, "ДФ=yyyyMMdd");
    
    Возврат СтрШаблон(Шаблон, СтрДата1, СтрДата2);
КонецФункции

Проблема контекста выполнения: Тонкий клиент против Сервера

В сообщениях форума часто обсуждается вопрос доступности методов. Проанализируем работу метода ПолучитьТелоКакСтроку(). Важно различать два похожих объекта:

  1. HTTPСервисОтвет — используется внутри кода самого HTTP-сервиса (на стороне «сервера-приемника»). В старых версиях платформы метод ПолучитьТелоКакСтроку здесь был ограничен в доступности.
  2. HTTPОтвет — это то, что мы получаем в ответ на вызов Соединение.Получить(Запрос). У этого объекта метод ПолучитьТелоКакСтроку() доступен практически везде: на тонком клиенте, сервере и даже в мобильном приложении.

Однако хорошей практикой считается выполнение всех сетевых операций на сервере 1С (в серверных модулях). Это позволяет избежать лишних задержек, проблем с прокси-серверами клиента и ограничений прав доступа на стороне ОС пользователя.

Рассмотрим правильную структуру вызова:


&НаКлиенте
Процедура ВыполнитьЗапрос()
    Результат = ВыполнитьЗапросНаСервере();
    // Обработка данных
КонецПроцедуры

&НаСервереБезКонтекста
Функция ВыполнитьЗапросНаСервере()
    НТТРСоединение = Новый HTTPСоединение("api.myserver.ru", 81, "Admin", "12345");
    НТТРЗапрос = Новый HTTPЗапрос("/base/hs/attendance_info/20230101");
    
    Попытка
        Ответ = НТТРСоединение.Получить(НТТРЗапрос);
        Если Ответ.КодСостояния = 200 Тогда
            Тело = Ответ.ПолучитьТелоКакСтроку();
            // Читаем JSON
            Чтение = Новый ЧтениеJSON;
            Чтение.УстановитьСтроку(Тело);
            Данные = ПрочитатьJSON(Чтение);
            Возврат Данные;
        Иначе
            Сообщить("Ошибка сервера: " + Ответ.КодСостояния);
        КонецЕсли;
    Исключение
        Сообщить("Не удалось связаться с сервером");
    КонецПопытки;
КонецФункции

Итоговый чек-лист для исправления ошибок

Если ваш сервис работает в браузере, но не работает в 1С, пройдите по следующим пунктам:

  1. Проверьте адрес ресурса: Убедитесь, что в HTTPЗапрос передается только относительный путь (без http:// и без имени сервера).
  2. Порт и протокол: Если веб-сервер слушает нестандартный порт (например, 81), убедитесь, что он указан в конструкторе HTTPСоединение, а не приклеен к строке адреса.
  3. Авторизация: Браузер может хранить кэшированные учетные данные. Проверьте, передаете ли вы правильные логин и пароль в HTTPСоединение.
  4. Метод запроса: Убедитесь, что вы используете Получить() для GET-запросов и ОтправитьДляОбработки() для POST-запросов, и что в самом HTTP-сервисе настроены соответствующие шаблоны.
  5. Логи сервера: Если ошибка сохраняется, включите подробный вывод ошибок в web.config (mode="Off") и посмотрите точный текст исключения, как это сделал автор темы.

Соблюдение этих правил позволит вам создавать надежные механизмы интеграции, которые будут работать стабильно в любых окружениях.

← На главную