При разработке интеграционных решений на базе HTTP-сервисов в платформе 1С:Предприятие 8.3 часто возникает необходимость узнать точный адрес, по которому опубликован сервис. Это критически важно для формирования гиперссылок в ответах (например, ссылок на скачивание файлов или связанных ресурсов), для реализации редиректов или для корректной работы в распределенных системах. Рассмотрим подробно, как решить эту задачу, используя встроенные инструменты платформы и особенности протокола HTTP. Для ускорения реализации базовой логики обработчиков можно применить общий модуль для быстрой организации HTTP-сервисов.
Самый простой и правильный способ получить адрес публикации внутри метода HTTP-сервиса — это обратиться к свойствам входящего запроса. Разберем по шагам, как это работает. Когда платформа принимает входящий вызов, она формирует объект типа HTTPСервисЗапрос. У этого объекта есть ключевое свойство БазовыйURL (на английском — BaseURL).
Проанализируем, что именно содержит БазовыйURL. Это строка, которая включает в себя:
http или https).Рассмотрим пример кода внутри метода обработки GET-запроса:
Функция ИмяМетодаGET(Запрос)
// Получаем базовый адрес сервиса
АдресПубликации = Запрос.БазовыйURL;
// Результат будет выглядеть примерно так:
// http://myserver.com/mybase/hs/MyServiceName
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки("Адрес публикации: " + АдресПубликации);
Возврат Ответ;
КонецФункции
Важно не путать свойство БазовыйURL со свойством ПолныйURL. Выясним причину этой путаницы. В то время как первый метод возвращает путь до корня сервиса, второй включает в себя абсолютно все данные запроса, включая относительный путь к конкретному ресурсу (шаблон URL) и параметры запроса (строка после знака вопроса).
Посмотрим на пример. Если клиент обращается по адресу: http://server/base/hs/service/v1/products?id=123, то:
Запрос.БазовыйURL вернет: http://server/base/hs/serviceЗапрос.ПолныйURL вернет: http://server/base/hs/service/v1/products?id=123Для формирования ссылок на другие методы этого же сервиса нам всегда следует использовать именно БазовыйURL.
Ситуация значительно усложняется, если ваша база 1С опубликована за промежуточным веб-сервером (например, Nginx, Apache или IIS), который выполняет роль прокси-сервера. Проанализируем проблему: в этом случае 1С работает "внутри" локальной сети, и свойство БазовыйURL может вернуть внутренний IP-адрес (например, http://10.0.0.5/...) вместо публичного доменного имени, которое видит клиент.
В таких случаях нам необходимо обратиться к коллекции Запрос.Заголовки. Разберем наиболее важные заголовки, которые помогут восстановить реальный адрес:
Посмотрим на пример универсального получения адреса хоста:
Хост = Запрос.Заголовки.Получить("X-Forwarded-Host");
Если Хост = Неопределено Тогда
Хост = Запрос.Заголовки.Получить("Host");
КонецЕсли;
Протокол = Запрос.Заголовки.Получить("X-Forwarded-Proto");
Если Протокол = Неопределено Тогда
// Пытаемся определить по БазовыйURL
Протокол = ?(Лев(Запрос.БазовыйURL, 5) = "https", "https", "http");
КонецЕсли;
Если вы разрабатываете решение для модели сервиса или используете области данных, платформа автоматически модифицирует URL. При обращении к конкретной области в адрес добавляется её идентификатор (например, /e1cib/data/123/).
Рассмотрим, как ведет себя БазовыйURL в этой ситуации. Платформа 1С спроектирована так, что свойство БазовыйURL автоматически включает в себя все необходимые сегменты пути для идентификации области. Это позволяет разработчику не беспокоиться о номере области — формируя ссылки на основе базового адреса, вы всегда попадете в нужный контекст данных.
Иногда возникает задача узнать адрес публикации в фоновом задании или при выполнении регламентных процедур, когда объекта Запрос просто не существует. Выясним, возможно ли это стандартными средствами.
К сожалению, в объектах метаданных 1С информация о том, где и как опубликована база, не хранится. Эта информация содержится в файле default.vrd на веб-сервере. Рассмотрим стратегии решения этой проблемы:
default.vrd возможно, если у процесса 1С есть права доступа к каталогу установки веб-сервера, но этот путь считается небезопасным и платформенно-зависимым.СтрокаСоединенияИнформационнойБазы(), но для серверных баз она вернет адрес кластера 1С, а не веб-публикации.Подводя итог, можно сказать, что для большинства задач внутри HTTP-сервиса достаточно использовать Запрос.БазовыйURL. Однако для высоконагруженных систем с балансировщиками и прокси-серверами всегда стоит предусмотреть логику анализа заголовка Host.
Важный момент: Если ваш сервис должен возвращать абсолютные ссылки на самого себя, всегда проверяйте соответствие протокола. Использование https в наше время является стандартом, и если ваша 1С "видит" только http из-за проксирования, не забудьте принудительно заменять протокол в возвращаемых строках, чтобы у клиента не возникало ошибок смешанного контента (Mixed Content).
Разберем финальный пример формирования ссылки на ресурс внутри сервиса:
// Предположим, нам нужно вернуть ссылку на файл с ID=456
ОтносительныйПутьКФайлу = "/files/get?id=456";
// Собираем полный путь
ПолныйПутьКРесурсу = Запрос.БазовыйURL + ОтносительныйПутьКФайлу;
// Если мы за прокси и нужен именно внешний адрес, используем Host
ВнешнийХост = Запрос.Заголовки.Получить("Host");
Если ВнешнийХост <> Неопределено Тогда
// Находим начало пути после домена в БазовыйURL
ПозицияСлэша = СтрНайти(Запрос.БазовыйURL, "/", , 3, 1); // Пропускаем http://
ПутьПослеХоста = Сред(Запрос.БазовыйURL, ПозицияСлэша);
ПолныйПутьКРесурсу = "https://" + ВнешнийХост + ПутьПослеХоста + ОтносительныйПутьКФайлу;
КонецЕсли;
Таким образом, комбинируя использование встроенного свойства БазовыйURL и анализ HTTP-заголовков, мы получаем гибкий и надежный инструмент для идентификации местоположения нашего сервиса в сети. Для проверки работы созданных методов и корректности передачи заголовков можно использовать обработку для тестирования HTTP-сервисов.