Модуль 3 · OpenAPI

Справочник «Стандартизация HTTP API» · модуль 3 · OpenAPI

Глава 3.2

3.2

Разделы
документа

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

Категория
Описание контракта
Уровень
Базовый
Связанные главы
3.1 Зачем описание · 3.3 FastAPI и OpenAPI · 6.2 Линтер
Зачем это знать
Чтобы читать чужое описание и понимать, чего в вашем не хватает

§1Карта документа

Файл описания — это один объект с несколькими полями верхнего уровня. Порядок в файле произвольный, но читать удобно в том порядке, в каком они перечислены ниже.

openapi.yaml

openapiредакция формата описания: 3.1.0
infoназвание, версия контракта, описание, контакты, лицензия
serversадреса, по которым API доступен
tagsгруппы операций и их описания
pathsадреса ресурсов, а внутри — операции по методам
componentsсхемы, заголовки, схемы безопасности — всё, на что ссылаются операции
securityтребования аутентификации: глобальные или у отдельных операций

Полный файл учебного сервиса открывается по адресу http://127.0.0.1:8000/openapi.json. Он большой — около тысячи строк — но состоит из повторяющихся кусков: разобрав один, вы прочитаете остальные.

Браузер с открытым /openapi.json: поля openapi 3.1.0, info с названием и версией, начало paths
Описание в браузере. Chrome умеет форматировать JSON: флажок «Автоформатировать» над текстом. Видны первые разделы — openapi, info, servers, начало paths.

§2info: кто это и какая версия

Раздел info отвечает на вопросы: что это за API, какая версия контракта, для чего он нужен и к кому идти с вопросами.

openapi/openapi.yaml · info
info:
  title: Service Desk API
  summary: Учебный стандартизированный REST API
  description: |
    Учебный API системы регистрации обращений в службу поддержки.
    …
  contact:
    name: API Team
    email: api-team@example.edu
    url: https://github.com/MaximBytecamp/api-standard-template
  license:
    name: MIT
    identifier: MIT
  version: 1.1.0

Спецификация не требует заполнять title, version, description и contact полностью — это требование правил проекта, то есть ужесточение по сравнению со стандартом. Zalando в своих правилах (рекомендация 218 «MUST contain API meta information») требует того же набора: название, версия по Semantic Versioning, описание и контакты владельца.

Зачем нужно поле contact

Вопрос по API может задать человек, который не знает ни автора описания, ни его команды. Поле contact — единственное место в контракте, где указано, к кому обращаться. В учебном проекте оно проверяется правилом линтера info-contact, и его отсутствие роняет сборку.

§3servers: где доступен API

Раздел перечисляет адреса, по которым сервис работает. У каждого адреса — описание, чтобы человек не перепутал тестовый контур с рабочим.

openapi/openapi.yaml · servers
servers:
  - url: http://127.0.0.1:8000
    description: Local development

В рабочем API таких записей обычно несколько: production, staging, песочница. Swagger UI показывает их списком, и запрос уходит на выбранный адрес. Описание у каждой записи снижает вероятность отправить изменяющий запрос на рабочий контур вместо тестового.

как это выглядит в реальном сервисе
servers:
  - url: https://api.example.com/api/v1
    description: Production
  - url: https://stage-api.example.com/api/v1
    description: Staging

§4tags: группы операций

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

openapi/openapi.yaml · tags
tags:
  - name: Tickets
    description: Обращения в службу поддержки: создание, просмотр, изменение и удаление

Каждая операция ссылается на тег своим полем tags. В учебном сервисе тег один — обращений всего один ресурс. В рабочем API теги обычно повторяют разделы предметной области: Tickets, Users, Reports, Authentication.

Swagger UI: заголовок группы Tickets с описанием и список операций под ним
Тег в Swagger UI. Заголовок группы и описание под ним взяты прямо из раздела tags. Операции без тега попадают в общий раздел default — правило проекта это запрещает.

§5paths: адреса и операции

Главный раздел документа. Ключ — адрес ресурса, внутри — операции по методам, у каждой операции — параметры, тело и ответы.

openapi/openapi.yaml · фрагмент paths
paths:
  /api/v1/tickets:
    get:
      tags: [Tickets]
      summary: Получить список обращений
      description: Возвращает страницу обращений. Размер страницы ограничен параметром limit.
      operationId: listTickets
      parameters:
        - name: status
          in: query
          required: false
          schema: { $ref: '#/components/schemas/TicketStatus' }
        - name: limit
          in: query
          schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TicketPage' }
        '422':
          description: Validation Error
          content:
            application/problem+json:
              schema: { $ref: '#/components/schemas/ProblemDetails' }
summaryКороткое название операции — его показывают в списке рядом с адресом.одна строка
descriptionПодробное объяснение: что делает, какие есть ограничения.абзац
operationIdУникальное имя операции. Генераторы клиентов превращают его в имя метода: client.listTickets().стабильно
parametersПараметры с указанием места (in: query, in: path, in: header) и схемы значения.вход
responsesВсе возможные ответы: код, описание, media type и схема тела.выход

Обратите внимание: у ответа 422 media type другой — application/problem+json. Так требуют правила проекта: все ошибки описываются единым форматом, и это проверяет линтер.

§6components: переиспользуемые части

Одна и та же схема нужна в нескольких операциях. Чтобы не копировать её, описание выносят в components и ссылаются через $ref.

openapi/openapi.yaml · components
components:
  schemas:
    Ticket: { … }
    TicketCreate: { … }
    TicketUpdate: { … }
    TicketPage: { … }
    ProblemDetails: { … }
  headers:
    XRequestId:
      description: Идентификатор запроса: значение клиента или UUID, созданный сервером
      schema: { type: string }
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

Выгода не только в объёме файла. Схема, описанная один раз, меняется один раз: добавили в Ticket поле — оно появилось во всех ответах, которые на неё ссылаются. При копировании такое изменение неизбежно где-нибудь забудут.

Правило простое: всё, что встречается в описании дважды, выносится в components.

§7security: чем защищено

Схема безопасности объявляется в components.securitySchemes, а операции ссылаются на неё полем security.

операция, требующая токен
  post:
      tags: [Tickets]
      summary: Создать обращение
      operationId: createTicket
      security:
        - BearerAuth: []

Пустой массив рядом с именем схемы означает «никаких дополнительных разрешений не требуется» — он нужен для схем OAuth 2.0, где там перечисляют scopes. Для Bearer-токена массив остаётся пустым.

Из этого объявления Swagger UI строит кнопку Authorize и добавляет заголовок к нужным запросам. Операции, у которых объявлена схема, помечаются значком замка. Если схема не объявлена, интерфейс не догадается: контракт молчит, и клиент узнает о необходимости токена только из ответа 401.

Не описывайте то, чего нет

OpenAPI позволяет объявить OAuth 2.0 с адресами авторизации. Если сервера авторизации нет, Swagger UI покажет кнопку, которая никуда не ведёт. Объявлять в описании схему, которой сервис не поддерживает, нельзя: это такое же несоответствие контракта поведению, как неверно указанный код ответа.

§8Частые ошибки

Операция без operationIdГенератор клиента придумает имя сам, и при следующей выгрузке оно изменится. Имя задаётся явно и не меняется после релиза.
Описан только успешный ответКлиент не напишет обработку 404 и 422, если о них не сказано. Перечисляются все ответы, которые операция может вернуть.
Схемы скопированы в каждую операциюИзменение придётся вносить в нескольких местах; одно обязательно забудут.
Нет контактов в infoЧитателю описания не к кому обратиться с вопросом. Правило проекта требует поля contact, его наличие проверяет линтер.
Единственный сервер — localhostВ рабочем API описание должно называть настоящие адреса, иначе Swagger UI отправит запрос не туда.

§9Проверьте себя

  1. Откройте /openapi.json учебного сервиса и найдите в нём все семь разделов верхнего уровня.
  2. Какие поля info требуют правила проекта и что произойдёт, если убрать contact?
  3. Зачем операции нужен operationId и почему его не стоит менять после релиза?
  4. Найдите в описании ответ 422. Какой у него media type и почему не application/json?
  5. Как из раздела securitySchemes появляется кнопка Authorize в Swagger UI?
Разделыopenapi · info · serverstags · pathscomponents · security
Операцияsummary · descriptionoperationId · tagsparameters · requestBodyresponses
Ссылки$ref: '#/components/schemas/Ticket'
БезопасностьsecuritySchemes: BearerAuthsecurity: [{BearerAuth: []}]

Справочник «Стандартизация HTTP API» · модуль 3 · глава 3.2Макаров Максим Николаевич

Кадр