Введение. Зачем это вообще нужно (и почему все статьи — не про то)
Реальная ситуация из прошлого. В чат с интегратором падает сообщение: «А какой формат даты вы принимаете? Структура 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 с полным описанием параметров и структур ответов.

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

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