Как "подружить" HTTP-сервисы со Swagger, рассказывает Денис, разработчик 1С в нашей команде
Содержание:
1. Введение. Зачем это вообще нужно (и почему все статьи — не про то).
2. Раздел 1: что такое Swagger/OpenAPI и зачем он 1С-нику.
3. Раздел 2: один подход, который реально работает.
4. Раздел 3: Установка и настройка расширения.
5. Раздел 4: описываем первый HTTP-сервис.
6. Раздел 5: проверка результата.
Введение. Зачем это вообще нужно (и почему все статьи — не про то)
Реальная ситуация из прошлого. В чат с интегратором падает сообщение: «А какой формат даты вы принимаете? Структура JSON есть? Можно пример?» И вы в десятый раз скриншотите свою тестовую обработку или скидываете ссылку на устаревший Word-файлик, который уже никто не обновлял.
В этот момент хочется одного, чтобы внешний мир просто понимал ваше API без ежеминутных уточнений. Чтобы разработчик на другой стороне открыл браузер и увидел: вот методы, вот параметры, вот примеры ответов. И чтобы эта документация всегда соответствовала реальности, потому что она является частью кода.
В мире за пределами 1С такая проблема решена давно и элегантно. Там есть Swagger (он же OpenAPI) — стандарт описания REST API, который понимают все: от фронтендеров до тестировщиков и генераторов клиентского кода.
В 1С же с этим — беда. Из коробки — ничего. Типовые статьи в интернете либо предлагают с нуля писать JSON-схемы руками (спойлер: никто не будет), либо ограничиваются абстрактными «создайте HTTP-сервис и опишите его в комментариях», умалчивая о граблях, на которых вы гарантированно споткнетесь.
А грабли эти увесистые. Например, тот самый CORS, который заставит вас проклясть тот день, когда вы решили подружить браузер с 1С. Или SetHandler 1С-application, молча сбрасывающий ваши заголовки. Или несоответствие типов, когда Swagger показывает одно, а 1С ждет совсем другое.
В этой статье будет инструкция для тех, кто устал читать консоли запросов вслух заказчику. Мы разберем:
- один из лучших подходов к внедрению Swagger в 1С;
- примеры с кодом и комментариями, пройдем по живому примеру HTTP-сервиса;
- и покажу некоторые «грабли», с которыми я столкнулся.
Поехали.
Раздел 1: что такое Swagger/OpenAPI и зачем он 1С-нику.
1.1. Немного теории
Swagger — это целая экосистема инструментов, в центре которой лежит спецификация OpenAPI Specification (OAS).
OpenAPI — это, если можно так сказать, технический паспорт, где на понятном (и человеку, и машине) языке описано:
- какие URL (методы) у нашего HTTP сервиса;
- какие параметры можно передать (и где — в заголовке, в строке запроса или в теле);
- какой формат данных (JSON, XML) он понимает;
- что он вернет в случае успеха, а что — при ошибке.
Этот «паспорт» можно написать вручную в формате JSON или YAML, а можно сгенерировать автоматически из кода. И вот здесь начинается магия.
На основе этого JSON-файла другие инструменты (например, Swagger UI) строят интерактивную веб-страницу.
Необходимо учесть, что наш Swagger поддерживает несколько интерфейсов (ReDoc, Scalar, Stoplight и RapiDoc). Об этом можно прочитать здесь.
Важно: столкнулся с проблемой при отображении сервиса в браузере, а именно непонятными ошибками, из-за которых описание в браузере вообще не генерировалось. Выход (в моем случае) в адресной строке указал интерфейс RapiDoc (http://<Адрес_опубликованной_базы>/hs/swagger/index.html?ui=RapiDoc ), и все «взлетело».
Мы для примеров будем использовать RapiDoc, и наша веб-страница будет выглядеть примерно так:
На этой странице любой желающий может:
- Увидеть полный список доступных методов API (на левой панели).
- Прочитать, что каждый метод делает, какие параметры принимает и что отдает.
- Тут же, в браузере, отправить тестовый запрос и увидеть реальный ответ от сервера.
Просто открыл браузер и работаешь.
1.2. Три железобетонных аргумента для внедрения.
- Стандартизация API. Все ваши методы и структуры данных описаны в едином, общепринятом формате. Интегратору не нужно вникать в «фирменный» стиль 1С. Он просто читает документацию так же, как читает ее для любого современного REST API.
- Автодокументирование и «единство кода и правды». Это ключевой момент. Если вы правильно организуете процесс, Swagger-спецификация будет генерироваться автоматически на основе вашего кода. Вы меняете логику — документация обновляется сама при следующей сборке. Забудьте про «документацию в Word».
- Упрощение тестирования и интеграции. Внешние системы и разработчики могут начать работать с вашим API немедленно, не отвлекая вас вопросами. Это экономит часы переписок и нервов с обеих сторон. Плюс вы сами можете использовать Swagger UI для быстрых тестов своей разработки.
1.3. Почему в 1С с этим сложно.
Платформа не умеет генерировать спецификацию по вашим HTTP-сервисам. Все, что мы будем делать дальше, — это описывать наши HTTP-сервисы, красиво и удобно.
Что потребуется от вас:
- только установка расширений в конфигурацию;
- иногда небольшие настройки веб-сервера (в случае каких-то трудностей).
И это нормально. Платформа 1С развивается в сторону веб-технологий, но пока что многие вещи приходится делать руками.
Раздел 2: один подход, который реально работает.
Swagger -1С – это расширение, которое ставится в конфигурацию, само подхватывает твои HTTP-сервисы через специальные общие модули-описатели и прямо в рантайме отдает и Swagger UI, и спецификацию.
Три причины использования:
- Живая документация. Расширение само генерирует спецификацию на лету — не надо руками запускать скрипты при каждом чихе.
- Минимум телодвижений. Установил расширение, включил галку публикации, создал модуль-описание по шаблону — всё работает.
- Проверка параметров из коробки. Расширение умеет само проверять входящие данные на соответствие.
Единственный момент — придется немного подружить это хозяйство с веб-сервером.
Раздел 3: Установка и настройка расширения.
3.1. Где брать.
3.2. Установка.
Заходим в конфигуратор целевой базы.
Создаем новое расширение (имя любое, например Swagger).
Через меню «Конфигурация -> Загрузить конфигурацию из файла» и выбираем наш файл расширения. Обновляем конфигурацию базы.
3.3. Публикация на веб-сервере.
Тут важный момент, про который забывают в половине инструкций.
После установки расширения нужно переопубликовать базу на веб-сервере и обязательно поставить галку: «Публиковать HTTP сервисы расширений по умолчанию».
Без этой галки ваше расширение будет лежать мертвым грузом, и по адресу /hs/swagger/index.html будет 404.
После публикации перезапустить веб-сервер. IIS, Apache — не важно. Просто рестарт, чтобы подхватились все настройки.
3.4. Проверка, что всё ожило.
Открываем браузер и идем по адресу:
http://<Адрес_опубликованной_базы>/hs/swagger/index.html*
* - добавляется имя интерфейса, например: ?ui=RapiDoc
Если видим картинку примерно такой, как на рисунке, то у вас все заработало.

Раздел 4: описываем первый HTTP-сервис.
4.1. Что хочет расширение.
Расширение ищет описания HTTP-сервисов в общих модулях, имена которых строятся по шаблону:
«<Имя_HTTP_сервиса>Описание».
То есть если ваш HTTP-сервис называется ОбменДанными, то общий модуль-описание должен называться ОбменДаннымиОписание. Регистр важен.
4.2. Живой пример: сервис остатков.
Для примера возьмем типовую задачу — HTTP-сервис, который отдает остатки по складу.
Имя HTTP-сервиса в метаданных: ОстаткиСклада.
Шаблон URL: /stocks.
Метод: GET.
Параметры запроса: storageCode (код склада, обязательный), productFilter (фильтр по товарам — массив ID, опционально).
Ответ: массив объектов с полями productId, quantity, price.
4.3. Создаем модуль-описание.
Создаем общий модуль с именем ОстаткиСкладаОписание.
В этом модуле нам нужно описать все методы нашего HTTP-сервиса. Три обязательные функции:

Вот как будет выглядеть описание для нашего GET-метода в функции ПолучитьОписаниеHTTPСервиса():
// Возвращает основной массив описаний HTTP-Сервиса
//
// Возвращаемое значение:
// Массив - Список сформированного описания методов HTTP-сервиса. См. https://zerobig.github.io/swagger-1c/docs/getting-started/methods_func_style
//
Функция ПолучитьОписаниеHTTPСервиса() Экспорт
Методы = Swag_Описание
.Метод("ОстаткиСкладаGET")
.ОписаниеМетода("Остатки товаров на складах")
.ДетальноеОписаниеМетода(НСтр("ru = 'Получение данных по остаткам на складах.'"))
.ПараметрURL("storageCode")
.ОписаниеПараметра("Код склада, например ""0897""")
.Тело().ТипТела("application/json")
.СхемаТела("ОстаткиСкладаGET")
.Ответ(200)
.ОписаниеОтвета("Success")
.ТипОтвета("application/json")
.СхемаОтвета("ОстаткиСклада_Ответ")
.Сформировать()
;
Возврат Методы;
КонецФункции
А вот так в функции ПолучитьОбъектыHTTPСервиса():
// Возвращает массив объектов описания HTTP-Сервиса
//
// Возвращаемое значение:
// Массив - Список сформированных объектов описания. См. https://zerobig.github.io/swagger-1c/docs/getting-started/objects_func_style
//
Функция ПолучитьОбъектыHTTPСервиса() Экспорт
Объекты = Новый Массив;
Объекты = Swag_Описание
.Объект("ОстаткиСкладаGET") // Описание объекта
.Свойство("productFilter")
.ОписаниеСвойства("Код номенклатуры через запятую")
.ТипЗначения("array")
.Схема("ТоварыОтбор")
.Объект("ТоварыОтбор")
.Свойство("id")
.ОписаниеСвойства("Код номенклатуры")
.ТипЗначения("string")
.Пример("0098778,0098777,0066778,0098668")
.Объект("ОстаткиСклада_Ответ")
.Свойство("id")
.ОписаниеСвойства("Код номенлатуры")
.ТипЗначения("string")
.Пример("202140")
.Свойство("name")
.ОписаниеСвойства("Наименование номенлатуры")
.ТипЗначения("string")
.Пример("Мыло детское 100гр")
.Свойство("quantity")
.ОписаниеСвойства("Количество")
.ТипЗначения("integer")
.Пример(456)
.Свойство("price")
.ОписаниеСвойства("Цена")
.ТипЗначения("string")
.Пример("541,5")
.Сформировать()
;
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Объекты, Swag_ОбщиеОписанияПереопределяемый.ОбъектErrors422());
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Объекты, Swag_ОбщиеОписанияПереопределяемый.ОбъектErrors404());
Возврат Объекты;
КонецФункции
4.4. А где же сам код?
Важный момент: модуль-описание не содержит исполняемого кода. В нем живут только описания сервиса. Сам обработчик как был в модуле HTTP-сервиса, там и остается. Расширение просто читает наши функции и превращает их в спецификацию.
Но если мы хотим использовать встроенную проверку параметров (а мы хотим), то в коде обработчика надо добавить вызов метода ПроверитьПараметры из расширения.

В модуле HTTP-сервиса ОстаткиСклада обработчик будет выглядеть примерно так:
функция stocksGET (Запрос)
// Проверяем входящие параметры по описанию из модуля ОстаткиСкладаОписание
РезультатПроверки = Swag_ОбработкаНТТР.ПроверитьПараметры(
"ОстаткиСклада", // Имя НТТР-сервиса
"GET", // Имя метода (должно совпадать с описанием)
Запрос // Сам запрос
);
Если Не ПустаяСтрока(РезультатПроверки) Тогда
Возврат Swag_ОбработкаНТТР.ПолучитьОтветОшибки(РезультатПроверки, Истина);
КонецЕсли;
// --- здесь основная логика получения остатков ---
МассивОстатков = МодульОбработкиНТТРСервисов.ПолучитьОстатки(Запрос.Параметры["storageCode"]);
Ответ = Новый НТТРСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(МассивОстатков);
// Проверяем ответ на соответствие описанию
Возврат Swag_ОбработкаНТТР.ПроверитьОтвет(
"ОстаткиСклада",
"GET",
Ответ
);
КонецФункции
Этот код делает две вещи:
- До выполнения логики проверяет, все ли обязательные параметры пришли и правильного ли они типа.
- После формирования ответа проверяет, соответствует ли структура данных тому, что мы обещали в описании.
Если что-то не так, расширение само вернет человекочитаемую ошибку. Красота.
Раздел 5: проверка результата.
После того, как модуль-описание создан и код обработчика дописан:
- Обновляем конфигурацию базы.
- Открываем браузер по адресу http://<сервер>/<база>/hs/swagger/index.html.
- Если всё сделано правильно, видим наш метод GET /stocks с полным описанием параметров и структур ответов.

4. Тыкаем Try, вводим код склада, жмем Execute и получаем реальный ответ от сервера прямо в браузере.
Некоторое описание на скриншотах для примера:

Мы прошли путь от полного отсутствия документации до работающего Swagger UI, который:
- автоматически генерируется;
- проверяет входящие параметры и ответы;
- позволяет интеграторам самим тестировать методы без нашего участия;
- не требует танцев с бубном при каждом изменении API.
Пришлось:
- поставить расширение;
- создать модули-описания для каждого HTTP-сервиса;
- приучить себя писать код описания сервисов определенным образом.
Но, поверьте моему опыту, когда в следующий раз интегратор вместо «а скиньте пример» просто откроет Swagger и сам всё увидит, вы скажете себе спасибо.
P.S. Весь код описания сервисов написан исключительно на тестовой базе для тестирования. Все исходники расширения и примеры кода из статьи можно найти в репозитории zerobig/swagger-1c на GitHub.
Вступайте в нашу телеграмм-группу Инфостарт