Разработка и отладка HTTP-сервисов в среде 1С:Предприятие часто преподносит сюрпризы. Типичная ситуация: вы написали сервис, опубликовали его на веб-сервере (IIS или Apache), вставили ссылку в адресную строку браузера и получили идеальный JSON. Однако при попытке вызвать этот же сервис из кода 1С с помощью объекта HTTPСоединение, система выдает ошибку выполнения или сообщает о «потенциально опасном значении в пути».
В данной статье мы подробно разберем, почему возникает такая разница в поведении, проанализируем ошибки веб-серверов и научимся правильно формировать запросы в коде 1С.
Рассмотрим первую и самую коварную проблему. При работе через Internet Information Services (IIS) программист может столкнуться со следующим сообщением: [HttpException]: Обнаружено потенциально опасное значение Request.Path, полученное от клиента (:). Выясним причину этого поведения.
Когда мы работаем в браузере, мы вводим полный URL, например: http://myserver/base/hs/service/method. Однако объектная модель 1С требует разделения этого адреса на две части:
HTTPСоединение.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, который находится в каталоге публикации базы 1С.
Для того чтобы разрешить обработку «опасных» символов, необходимо найти секцию <system.web> и добавить (или отредактировать) параметр httpRuntime:
<configuration>
<system.web>
<httpRuntime requestPathInvalidCharacters="" />
</system.web>
</configuration>
Установка пустого значения в requestPathInvalidCharacters отключает проверку на недопустимые символы. Внимание: это снижает уровень безопасности сервера, поэтому рекомендуется использовать этот метод только в закрытых корпоративных сетях и отдавать предпочтение правильному формированию URL или использованию параметров запроса (URL Parameters) вместо сегментов пути.
При переходе с IIS на Apache пользователи часто сталкиваются с ошибкой 403 Forbidden или AH00127: Cannot map GET /. Выясним причину, проанализировав лог-файлы Apache.
В отличие от Windows и IIS, сервер Apache (особенно на Linux) крайне чувствителен к регистру символов в URL. Рассмотрим типичные проблемы:
Attendance_Info, а в коде вы обращаетесь к attendance_info, Apache может не сопоставить запрос с публикацией 1С..../hs/my_service (без слэша в конце) могут интерпретироваться сервером как попытка доступа к директории, а не к ресурсу. Попробуйте добавить слэш: .../hs/my_service/.%20, а кириллицу в соответствующий URL-encode. В 1С при формировании АдресРесурса это нужно делать вручную.Пример кодирования параметров в 1С:
Функция ПодготовитьПуть(ДатаНачала, ДатаОкончания)
Шаблон = "/base/hs/attendance_info/%1/%2";
// Используем кодирование, если в параметрах могут быть спецсимволы
СтрДата1 = Формат(ДатаНачала, "ДФ=yyyyMMdd");
СтрДата2 = Формат(ДатаОкончания, "ДФ=yyyyMMdd");
Возврат СтрШаблон(Шаблон, СтрДата1, СтрДата2);
КонецФункции
В сообщениях форума часто обсуждается вопрос доступности методов. Проанализируем работу метода ПолучитьТелоКакСтроку(). Важно различать два похожих объекта:
HTTPСервисОтвет — используется внутри кода самого HTTP-сервиса (на стороне «сервера-приемника»). В старых версиях платформы метод ПолучитьТелоКакСтроку здесь был ограничен в доступности.HTTPОтвет — это то, что мы получаем в ответ на вызов Соединение.Получить(Запрос). У этого объекта метод ПолучитьТелоКакСтроку() доступен практически везде: на тонком клиенте, сервере и даже в мобильном приложении.Однако хорошей практикой считается выполнение всех сетевых операций на сервере 1С (в серверных модулях). Это позволяет избежать лишних задержек, проблем с прокси-серверами клиента и ограничений прав доступа на стороне ОС пользователя.
Рассмотрим правильную структуру вызова:
&НаКлиенте
Процедура ВыполнитьЗапрос()
Результат = ВыполнитьЗапросНаСервере();
// Обработка данных
КонецПроцедуры
&НаСервереБезКонтекста
Функция ВыполнитьЗапросНаСервере()
НТТРСоединение = Новый HTTPСоединение("api.myserver.ru", 81, "Admin", "12345");
НТТРЗапрос = Новый HTTPЗапрос("/base/hs/attendance_info/20230101");
Попытка
Ответ = НТТРСоединение.Получить(НТТРЗапрос);
Если Ответ.КодСостояния = 200 Тогда
Тело = Ответ.ПолучитьТелоКакСтроку();
// Читаем JSON
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Тело);
Данные = ПрочитатьJSON(Чтение);
Возврат Данные;
Иначе
Сообщить("Ошибка сервера: " + Ответ.КодСостояния);
КонецЕсли;
Исключение
Сообщить("Не удалось связаться с сервером");
КонецПопытки;
КонецФункции
Если ваш сервис работает в браузере, но не работает в 1С, пройдите по следующим пунктам:
HTTPЗапрос передается только относительный путь (без http:// и без имени сервера).HTTPСоединение, а не приклеен к строке адреса.HTTPСоединение.Получить() для GET-запросов и ОтправитьДляОбработки() для POST-запросов, и что в самом HTTP-сервисе настроены соответствующие шаблоны.web.config (mode="Off") и посмотрите точный текст исключения, как это сделал автор темы.Соблюдение этих правил позволит вам создавать надежные механизмы интеграции, которые будут работать стабильно в любых окружениях.