Получить консультацию

HTTP-сервисы в 1С 8.3 с примерами

В данной статье мы рассмотрим основные сценарии создания своих HTTP-сервисов в 1С. На нескольких примерах мы разберем устройство HTTP-сервисов в 1С – как их настраивать в конфигураторе, какие объекты и методы языка используются. Также познакомимся с некоторыми нюансами разработки HTTP-сервисов, и слегка коснемся способов их тестирования и отладки.

Содержание

Немного теории о http-сервисах в 1С 8.3

HTTP-сервисы – это объекты конфигурации, которые позволяют обрабатывать входящие HTTP запросы, и по сути “превращают” 1С в бэкенд-движок. В их основе лежит использование протокола  HTTP и его методов, таких как GET, POST, UPDATE и других. Программные средства платформы позволяют анализировать URL-адрес запрошенного ресурса, параметры HTTP запроса, его заголовки и тело, и в зависимости от этого возвращать тот или иной HTTP-ответ.
Входящий HTTP запрос включает в себя URI-адрес, имя метода, заголовки, параметры URL(обязательные части адресной строки) и параметры запроса(необязательные части адресной строки), а также может содержать тело запроса.
После обработки входящего запроса HTTP сервис должен вернуть ответ, который состоит из заголовков, кода ответа и тела ответа. Телом может быть простой текст, двоичные данные, файл, HTML-документ и т.д.
Жестких требований к структуре адреса URI и к обработке методов нет, но существуют распространенные соглашения. Например, будет дурным тоном использовать метод DELETE для создания элементов, или метод GET для удаления.
Одним из подходов к архитектуре http-сервисов является REST API, но далеко не всегда при разработке http-сервисов целесообразно во всем следовать методологии REST.

В отличие от SOAP сервисов, HTTP сервисы гораздо менее формализованные и более гибкие, что одновременно является и достоинством и недостатком.
За дополнительной теоретической информацией можно проследовать по ссылкам:
Список заголовков HTTP
Список кодов состояния HTTP
Еще больше про протокол HTTP от Mozilla

Пример простого http-сервиса

Как водится, любую теорию лучше закреплять на практике. Создадим простой http сервис, который будет возвращать текст “Hello world”.
Для этого перейдем в конфигуратор и откроем ветку метаданных Общие / HTTP-сервисы. Имя сервиса как нравится, например, “HelloWorld”. Важным свойством является корневой URL – это та часть адреса, которая будет стоять перед URL для конкретных шаблонов.

Как прочитать файл Excel в 1С 8.3

Следующее, что необходимо сделать – добавить шаблон на вкладке Шаблоны URL. По этому шаблону платформа будет осуществлять диспетчеризацию входящих запросов – если текст URL будет соответствовать какому-то шаблону, будет вызван обработчик соответствующего метода. Если же ни один шаблон не подошел, будет возвращен ответ с кодом ошибки.

Добавим шаблон “/say”. В итоге получим следующий URL 127.0.0.1/demohttp/hs/helloworld/say. По частям он выглядит так: {адрес публикации базы}/hs/{корневой URL}{шаблон}hs в адресе, как не трудно догадаться, означает “HTTP сервисы”.

Простой http-сервис в 1С пример 2

Каждый шаблон URL может принимать запросы с разными методами. Для простого примера HTTP-сервиса добавим метод GET, и укажем имя события обработчика. Если не указать, платформа сгенерирует имя самостоятельно.

Простой http-сервис в 1С пример 3

Платформа автоматически создаст заготовку процедуры-обработчика, и нам останется только дополнить ее своим кодом.
Чтобы сервис что-то возвращал, кроме кода ответа, нам понадобится установить тело ответа. Нам доступно три варианта – установить тело из файла, из потока либо из строки. Последнее мы и используем.

Функция GetMessage(Запрос)
	Ответ = Новый HTTPСервисОтвет(200);
	Ответ.УстановитьТелоИзСтроки("Hello World!");
	Возврат Ответ;
КонецФункции

Чем хорош метод GET – так это тем, что он прекрасно вызывается из адресной строки браузера – достаточно указать нужный URL, и браузер отправит HTTP запрос, и отобразит ответ в текущем окне или вкладке.

Но для того, чтобы внешний мир “увидел” ваш сервис, необходимо опубликовать информационную базу на веб-сервере. Это может быть Apache либо Microsoft IIS – выбирайте что вам проще и удобнее. Важно – для публикации на веб-сервере конфигуратор необходимо запустить от имени администратора ОС!
В настройках публикации необходимо отметить флажком нужный HTTP-сервис и проставить также флажок “Публиковать HTTP сервисы по умолчанию“.

Простой http-сервис в 1С пример - публикация на веб сервере

Для проверки наберем адрес нужного нам сервиса в браузере.

ПараметрыURL

Теперь давайте немного усложним наш сервис, а заодно познакомимся с передачей параметров.
При создании шаблона мы можем указывать не только фиксированные части, но и так называемые именованные секции. Они представляют собой часть адреса, указанную в фигурных скобках. Например, мы можем указать шаблон “/say/{name}”
В этом случае при обработке входящего запроса нужный параметр будет содержаться в коллекции ПараметрыURL. Ключ коллекции – это сама именованная секция, а значение – то что было фактически указано в адресе URL. Например, если мы укажем /say/admin, то в коллекции у нас будет один элемент – с ключом  “name” и значением “admin”.

Обратите внимание, что указание значения для именованных секций является обязательным. Т.е. если есть секция name, ее обязательно придется заполнить, чтобы сработал корректный шаблон. Либо нужно предусматривать несколько шаблонов – например один с именованной секцией, другой – без нее. В противном случае мы получим ошибку 404.

Немного изменим код нашего сервиса, чтобы он выводил в ответном сообщении все значения параметров URL. Здесь для того, чтобы браузер корректно отобразил кириллические символы, мы указываем заголовок Content-Type, в котором “говорим” браузеру, что в ответе – обычный текст в нужной нам кодировке utf-8.
Так как ПараметрыURL – это обычное фиксированное соответствие, то и работать мы с ним будем как с фиксированным соответствием, и для доступа к значениям можем использовать метод Получить(), либо же перебрать коллекцию в цикле.

Функция GetMessage(Запрос)
	
	ТекстОтвета = "Hello World! ";
	
	Для Каждого ПараметрАдреса Из Запрос.ПараметрыURL Цикл
		ТекстОтвета = ТекстОтвета + СтрШаблон("ПараметрыURL. ключ: %1, значение: %2", ПараметрАдреса.Ключ, ПараметрАдреса.Значение) + Символы.ПС;
	КонецЦикла;	
	
	Ответ = Новый HTTPСервисОтвет(200);
	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Content-Type", "text/plain; charset=utf-8");
	Ответ.Заголовки = Заголовки;
	Ответ.УстановитьТелоИзСтроки(ТекстОтвета);
	
	Возврат Ответ;
	
КонецФункции
Простой http-сервис в 1С пример 5

ПараметрыЗапроса

Но далеко не всегда такой подход удобен – иногда текст URL должен быть гибким, с необязательными параметрами. Например, мы хотим, чтобы один и тот же шаблон мог возвращать текущую дату, сообщение пользователя и его электронную почту, как по отдельности, так и в любой комбинации из этих трех значений. В этом нам помогут необязательные параметры запроса.

В шаблоне они не указываются, и анализируются исключительно в коде обработчика. Параметры запроса пишутся после вопросительного знака в виде пары ключ=значение, и разделяются знаком амперсанда.
Вот несколько примеров:
http://127.0.0.1/demohttp/hs/helloworld/say/admin?text=привет от меня
http://127.0.0.1/demohttp/hs/helloworld/say/admin?text=привет от меня&date=true&email=true
http://127.0.0.1/demohttp/hs/helloworld/say/admin?email=true

Данные параметры не являются позиционными, их можно указывать в любом порядке. И тут мы подходим к одному из свойств HTTP-сервисов, которые являются как большим преимуществом, так и большим же недостатком. Речь идет о гибкости. Но HTTP-сервисы не предоставляют возможности снаружи узнать, какие параметры они имеют, какие допустимые значения этих параметров, и какой ответ можно ожидать при передаче тех или иных параметров. И все зависит от наличия и качества документации, которую разработчик сервиса предоставляет пользователям этого сервиса.

Давайте рассмотрим код обработчика, который позволит обработать параметры запроса. Его мы вставим перед выводом параметров URL. Здесь мы явно проверяем, заполнен ли параметр, и чему он равен, т.к. необязательные параметры на то и необязательные, что могут отсутствовать либо принимать неверные значения. Любые неподходящие параметры мы не обрабатываем, а ищем только известные нам заранее.

	ТекстПараметровЗапроса = "";
	Сообщение = Запрос.ПараметрыЗапроса.Получить("text");
	Если ЗначениеЗаполнено(Сообщение) Тогда
		ТекстПараметровЗапроса = ТекстПараметровЗапроса + "Сообщение: " + Сообщение + Символы.ПС;
	КонецЕсли;	
	ПризнакДаты = Запрос.ПараметрыЗапроса.Получить("date");
	Если ЗначениеЗаполнено(ПризнакДаты) И ПризнакДаты = "true" Тогда
		ТекстПараметровЗапроса = ТекстПараметровЗапроса + "сегодня: " + Формат(ТекущаяДата(),"ДФ=dd.MM.yyyy") + Символы.ПС;
	КонецЕсли;
	ПризнакПочты = Запрос.ПараметрыЗапроса.Получить("email");
	Если ЗначениеЗаполнено(ПризнакДаты) И ПризнакДаты = "true" Тогда
		ТекстПараметровЗапроса = ТекстПараметровЗапроса + "email: " + "foo@bar.ru" + Символы.ПС;
	КонецЕсли;	
	Если ЗначениеЗаполнено(ТекстПараметровЗапроса) Тогда
		ТекстОтвета = ТекстОтвета + ТекстПараметровЗапроса;
	КонецЕсли;
HTTP запрос ПараметрыЗапроса

Заголовки в HTTP сервисах

Работу с заголовками можно условно разделить на две части – анализ и обработку заголовков входящего запроса, и формирование заголовков для ответа.
Существует большое количество стандартных заголовков, которые могут передаваться браузером или вызывающим приложением. Но также разработчик может предусмотреть и свои собственные заголовки. Обрабатывать их можно аналогичным образом, т.к. коллекция Заголовки – все то же Фиксированное соответствие.

При помощи заголовков можно, например, передавать настройки авторизации, вариант формирования ответа (xml, json, html и т.д.), и в принципе любую информацию, которая может понадобиться при формировании ответа.

HTTP сервис заголовки

Как при помощи Http-сервисов из 1С возвращать файлы, картинки, веб-страницы?

С картинками, файлами и статичными html-страницами все довольно прозаично. Мы получаем входящий запрос, адресованный к какому-нибудь ресурсу, например к картинке “image.png”. Дальше мы тем или иным образом получаем двоичные данные этого ресурса – например, из хранилища значения в регистре сведений. Для этого мы можем анализировать заголовки, параметры запроса и параметры URL. А дальше остается только указать корректный MIME тип и поместить двоичные данные в тело ответа.

Кроме того, тело ответа может быть сформировано из строки в кодировке Base64. Например, мы можем эту строку хранить также в регистре сведений, или собирать по частям, или получать из внешнего сервиса, и т.п. В этом случае всего лишь заменяем УстановитьТелоИзДвоичныхДанных на УстановитьТелоИзСтроки.

Рассмотрим пару примеров – первый будет отображать картинку в браузере, второй – скачает документ Word. Картинку мы используем из стандартной библиотеки картинок, а документ будет храниться в общем макете с видом Двоичные данные. Обратите внимание, для упрощения примеров мы не анализируем заголовки и параметры, а возвращаем всегда одно и то же. На практике же код может быть весьма и весьма сложным, но суть будет та же.

Функция GETpicture(Запрос)
	КартинкаДД = БиблиотекаКартинок.БизнесПроцесс.ПолучитьДвоичныеДанные();
	Ответ = Новый HTTPСервисОтвет(200);
	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Content-Type", "image/png");
	Ответ.Заголовки = Заголовки;
	Ответ.УстановитьТелоИзДвоичныхДанных(КартинкаДД);
	Возврат Ответ;
КонецФункции

Функция GETword(Запрос)
	Ответ = Новый HTTPСервисОтвет(200);
	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
	Ответ.Заголовки = Заголовки;
	Ответ.УстановитьТелоИзДвоичныхДанных(ПолучитьОбщийМакет("word"));
	Возврат Ответ;
КонецФункции

Аналогичным образом можно формировать и любые другие статичные ресурсы – css-файлы, html-страницы, pdf-документы, видео, аудио и т.д.

А вот с динамически формируемыми HTML страницами все несколько веселее. Суть в том, что мы можем возвращать как фрагмент отдельно взятой html-страницы в виде куска html-кода, так и целиком сверстать страницу с нуля на стороне сервера (т.е. на стороне 1С). Но и это еще не все. Многие популярные фреймворки используют для формирования html-страниц данные в JSON или XML формате. Т.е. тут задача сводится к формированию нужного текста JSON с соответствующим Content-Type. О работе с JSON вы можете почитать в вот этой моей статье.

Обработка POST-запросов

POST запросы служат для передачи с вызывающей стороны какой-то информации для дальнейшей обработки. Это может быть загрузка файла в базу данных, запрос на создание документа, на формирование отчета либо какие-то другие действия. Применительно к различным интеграциям чаще всего POST запросы служат для обмена информацией в JSON формате – получаем какой-то JSON на вход, обрабатываем, и отдаем другой JSON на выход.

Поэтому обработка метода POST зависит от задачи и от содержимого тела запроса. Кроме того, на логику обработки POST-запроса могут влиять и заголовки, и параметры URL, и параметры запроса. Но чаще всего всю необходимую информацию все-таки помещают в тело запроса (Body).
Чтобы преобразовать тело запроса в то, что нам нужно, мы используем методы объекта HTTPСервисЗапрос – их всего три, и они служат для получения тела запроса как строки, потока либо двоичных данных соответственно.

ПолучитьТелоКакДвоичныеДанные целесообразно использовать, когда мы, например, хотим загрузить в 1С переданную картинку или файл. ПолучитьТелоКакПоток – подходит для обработки больших объемов данных порционно. А ПолучитьТелоКакСтроку – отлично подойдет, если нам нужно обработать текстовые данные – тот же  JSON или XML.

Предположим, что нам нужен сервис, который вернет остатки товаров, с использованием фильтров. В этом случае на вход мы можем получать JSON с фильтрами, например такой:
{
goods: [0001, 0002, 0003],
organisationID: 12345,
storeID: 789456,
date: 2023-01-21T12:34:56.511Z
}
И в ответ мы сформируем другой JSON – с указанием остатков по товарам с кодами 0001, 0002 и 0003, по организации с ИД 12345, по складу 789456, и на указанную дату.
Нам понадобится создать шаблон для получения остатков, например /stocks/{format}. format мы можем анализировать для того, чтобы сформировать ответ в нужном виде – например, в xml, json или csv. Естественно, мы это можем передать и в виде параметра запроса, и в виде заголовка, и в теле самого запроса. Так что однозначного подхода тут нет и быть не может.
В шаблоне создадим метод POST, и пропишем код обработчика.

Функция ПолучитьОбъектОтвета(СтруктураВходныхПараметров)
	// Дальше разбираем структуру входных параметров, формируем запрос остатков с указанием фильтров, и результат упаковываем снова в JSON
	// В качестве примера вернем тестовые данные
	Остатки = Новый Массив;
	СтруктураТоваров = Новый Структура("goods, qty", "0001", 15);
	Остатки.Добавить(СтруктураТоваров);
	Возврат Остатки;
КонецФункции

Функция POSTstocks(Запрос)
	ФорматОтвета = Запрос.ПараметрыURL.Получить("format");
	Если ФорматОтвета = "json" тогда
		
		СтрокаJSON = Запрос.ПолучитьТелоКакСтроку();
		
		ЧтениеJSON = Новый ЧтениеJSON;
		ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
		СтруктураВходныхПараметров = ПрочитатьJSON(ЧтениеJSON);
		ЧтениеJSON.Закрыть();
		
	    ОбъектОтвета = ПолучитьОбъектОтвета(СтруктураВходныхПараметров);
		ПараметрыJSON = Новый ПараметрыЗаписиJSON(, Символы.Таб);
		ЗаписьJSON = Новый ЗаписьJSON;
		ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
		ЗаписатьJSON(ЗаписьJSON, ОбъектОтвета);
		СтрокаJSON = ЗаписьJSON.Закрыть();
		
	ИначеЕсли ФорматОтвета = "xml" тогда
		// тут код для формирования ответа в xml 
	ИначеЕсли ФорматОтвета = "csv" тогда
		// тут код для формирования ответа в csv 
	Иначе
		Ответ = Новый HTTPСервисОтвет(500);
		Ответ.УстановитьТелоИзСтроки("неизвестный формат данных!");
		Возврат Ответ;
	КонецЕсли;
	
	Ответ = Новый HTTPСервисОтвет(200);
	Возврат Ответ;
	
КонецФункции

Отладка HTTP-сервисов

Для того, чтобы конфигуратор перехватывал вызовы HTTP сервисов при отладке, необходимо в настройках отладки включить соответствующий объект. Простые сервисы с методами GET, без сложных заголовков, можно вызывать непосредственно из адресной строки браузера.

Отладка HTTP сервисов

Средствами 1С

Вызвать HTTP сервис мы можем из 1С, при помощи объекта HTTP-запрос. Как пользоваться HTTP-запросами, читайте вот в этой статье. Простейший вызов нашего сервиса будет такой:

	СоединениеHTTP = Новый HTTPСоединение("127.0.0.1");
	ЗапросHTTP = Новый HTTPЗапрос("demohttp/hs/helloworld/say/admin");
	Ответ = СоединениеHTTP.Получить(ЗапросHTTP);
	Сообщить(Ответ.ПолучитьТелоКакСтроку());

К сожалению, ограничения учебной версии платформы не предполагают одновременного запуска 1С в пользовательском режиме и вызова http сервисов, поэтому если вы используете учебную версию платформы, вам для отладки подойдет второй способ.

Postman

Для работы с более сложными запросами лучше пользоваться специализированными инструментами. Одним из таких инструментов является Postman. Он позволяет формировать очень сложные HTTP запросы, на лету настраивать параметры авторизации, заголовки, тело запроса, и многое другое. Есть большое количество обучающих материалов – статей и видео, посвященных работе с Postman, поэтому в данной статье мы его подробно рассматривать не будем.
И все же пару моментов стоит указать.

При работе с локальным сервером localhost, он же 127.0.0.1, в веб-версии postman понадобится установить приложение postmanAgent. Но я рекомендую скачать десктопную версию Postman и пользоваться ей. Тогда можно будет указывать доменную авторизацию NTLM без танцев с бубном.

На этом буду закругляться, статья и так вышла весьма объемная. За рамками материала осталось еще немало нюансов – авторизация, использование JWT токенов, некоторые моменты при публикации базы, и др. Что ж, если материал интересен – оставляйте комментарии, подготовлю вторую часть!

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

3 × четыре =

К НАЧАЛУ