Найти в Дзене

Погружение в Swagger: от основ до сложных кейсов в Nest.js

Привет! Меня зовут Александр Панфилов, я фронтенд-разработчик и тимлид с 9-летним опытом. В этой статье я хочу поделиться своим опытом глубокой работы со Swagger — инструментом, который кажется простым только на первый взгляд. На практике же его тонкости могут отнять немало времени, и сегодня я разберу именно те моменты, которые потребовали от меня наибольших усилий. В своей работе столкнулся с тем, что Swagger игнорирует мой заголовок authorization; не знал, как описать два разных типа запросов к одному эндпоинту и т. д. Далее по тексту я опишу, как мне удалось обойти такие проблемы. Что такое Swagger и OpenAPI? Swaggerи OpenAPI — это, по сути, синонимы для разработчика. Речь идет о наборе спецификаций, которые описывают структуру запросов и ответов для каждого эндпоинта API Почему я решил погрузиться в эту тему? В рамках рабочего проекта мне пришлось временно выполнять роль аналитика, что подразумевало активную работу со спецификацией эндпоинтов. Работа с параметрами: нестандартный п

Привет! Меня зовут Александр Панфилов, я фронтенд-разработчик и тимлид с 9-летним опытом. В этой статье я хочу поделиться своим опытом глубокой работы со Swagger — инструментом, который кажется простым только на первый взгляд. На практике же его тонкости могут отнять немало времени, и сегодня я разберу именно те моменты, которые потребовали от меня наибольших усилий.

В своей работе столкнулся с тем, что Swagger игнорирует мой заголовок authorization; не знал, как описать два разных типа запросов к одному эндпоинту и т. д. Далее по тексту я опишу, как мне удалось обойти такие проблемы.

Что такое Swagger и OpenAPI?

Swaggerи OpenAPI — это, по сути, синонимы для разработчика. Речь идет о наборе спецификаций, которые описывают структуру запросов и ответов для каждого эндпоинта API

Почему я решил погрузиться в эту тему?

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

  • Общаясь с Java-разработчиками, я открыл для себя подход API-first:
    Смежные команды заключают контракт по эндпоинтам.
  • Контракт детально описывается и согласовывается. Утвержденная спецификация используется для генерации кода как на бэкенде, так и на фронтенде.
  • Автоматическая кодогенерация — ключевой фактор. Нам удалось настроить этот процесс, что значительно ускорило разработку.

Работа с параметрами: нестандартный пример с enum

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

Итоговый пример настройки параметра type
Итоговый пример настройки параметра type

Раньше я плотно не работал с настройкой Swagger и был удивлен, что редактировать поля можно только после нажатия кнопки «Try it out».

Подробная документация параметра type на примере фреймворка nest.js
Подробная документация параметра type на примере фреймворка nest.js

Структура параметра с enum:

  • name — имя параметра;
  • enumName — произвольное имя enum;
  • enum — допустимые значения;
  • description — описание;
  • examples — примеры значений. Это объект, где каждый ключ содержит:
  1. value — конкретное значение;
  2. description — пояснение, зачем оно нужно.

Использование examples особенно удобно: это дает полное представление о возможных значениях параметра.

Несколько типов тел запроса для одного эндпоинта

Иногда один эндпоинт должен обрабатывать разные форматы данных. В Swagger это реализуется через механизм examples.

Пример настройки тела запроса с возможностью выбора двух вариантов тел в запросе эндпоинта
Пример настройки тела запроса с возможностью выбора двух вариантов тел в запросе эндпоинта

В решении этого вопроса мне также помог examples.

Пример реализации описания тела запроса эндпоинта с возможностью выбора тела запроса
Пример реализации описания тела запроса эндпоинта с возможностью выбора тела запроса
  • description — пояснение, для чего предназначено это тело.
  • schema — JSON-схема тела запроса. Она здесь используется намеренно для добавления возможности выбора между используемыми вариантами ответа;
    anyOf — оператор, позволяющий выбрать одну из нескольких схем. Как вариант, можно еще использовать oneOf — будет тот же смысл, но я посчитал, что здесь лучше использовать anyOf.
    $ref и getSchemaPath — ссылки на DTO-схемы (в моем случае — на основе class-validator).
  • examples — примеры для каждой схемы.

Важно! Если указать несколько схем в schema, но не заполнить examples, интерфейс Swagger не предоставит выбора.

В интерфейсе указано две и более схемы, но не заполнен examples
В интерфейсе указано две и более схемы, но не заполнен examples

Заголовки и авторизация

Моя авторизация построена на токенах, передаваемых в заголовках. Однако при добавлении заголовка authorizationв Swagger он не отправлялся в запросе. Оказалось, что в nestjs/swagger этот заголовок по умолчанию игнорируется.

Пример заголовка в swagger
Пример заголовка в swagger

На картинке приведен заголовок. Когда нажимал «try it», то запрос уходил, но заголовка в нем не было.

Решение: Я добавил несколько способов авторизации — через accessToken и refreshToken.

Два способа авторизации — через access и refresh токены
Два способа авторизации — через access и refresh токены

Чтобы использовать кастомный заголовок, нужно:

  1. Нажать на значок замка;
  2. Ввести актуальный токен;
  3. Важный момент: Swagger запоминает значение и автоматически подставляет его во все запросы с этой авторизацией.
Функция для сокрытия заголовока authorization
Функция для сокрытия заголовока authorization

Со временем я решил скрыть стандартный заголовок authorization, чтобы не вводить в заблуждение.

Чего лично мне не хватает в работе со swagger в nest.js?

Главный недостаток — отсутствие встроенной генерации кода по OpenAPI-спецификации, как это реализовано в Java. В остальном инструмент полностью отвечает моим запросам.

Выводы

  • Swagger — мощный инструмент, но его тонкости требуют времени на освоение.
  • Использование examples и anyOf значительно расширяет возможности документации.
  • Работа с заголовками в Nest.js имеет свои нюансы, но они решаемы.
  • ИИ может ускорить работу, но лично я предпочитаю писать код вручную — так надежнее.

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

Удачи в освоении Swagger)