Как сгенерировать спецификацию swagger3 (OpenAPI3) в (.json / .yaml) из файлов protobuf (.proto)?

Мой первоначальный вариант использования:

Я создаю приложение в GO с gRPC сервером (используя protobuf) и помещаю его в HTTPS-сервер (используя gin). Для использования клиентам публикуется только HTTPS-сервер (я имею в виду, что к моему приложению можно получить доступ через REST API, который затем набирает номер на конечной точке gRPC), и я публикую его, используя Swagger OpenAPI3 (версия 3 - это здесь главное требование) спецификация. Требуются и gRPC, и HTTPS, и любое решение должно соответствовать этой архитектуре.

Я не хочу поддерживать спецификацию моего сервера в двух местах, то есть я не хочу поддерживать оба файла proto (.proto) и спецификацию swagger (.json/.yaml). Поскольку мне абсолютно необходимо писать прото-файлы для генерации сервера gRPC, я хочу автоматизировать генерацию спецификации swagger (OpenAPI3).

Где я:

Я могу создать swagger спецификацию OpenAPI2 из файлов protobuf (.proto), используя библиотеку grpc-gateway примерно так: grpc-rest-go-example. Но мое требование - OpenAPI3; более конкретно, я хочу использовать функцию oneOf в OpenAPI3 и сопоставить ее с функцией oneof proto. Это невозможно с OpenAPI2, поскольку он не позволяет API иметь тело запроса / ответа с несколькими определениями типов, что было функцией, добавленной в OpenAPI3 путем включения конструкций oneOf, anyOf и allOf.

Пытаясь сделать это, я наткнулся на эту библиотеку GoogleAPI googleapis / gnostic, описание которой:

Этот репозиторий содержит инструмент командной строки Go, который преобразует описания OpenAPI JSON и YAML в эквивалентные представления буфера протокола и обратно.

На первый взгляд кажется, что это в точности решает мою проблему, но, как оказалось, эта библиотека преобразует только двоичный буфер протокола (protobuf) (.pb) и файлы Swagger OpenAPI2 / OpenAPI3 (.json/.yaml), что подводит меня к моей новой проблеме.

Так, например, для следующего .pb файла:


�3.0.1�…�
�Example service��Example service description*�
�Example contact2=

Apache 2.0�/http://www.apache.org/licenses/LICENSE-2.0.html:�1.0�!
�//localhost:9999/example/api/v1"â�
�
�/exampleResource��"���Example API��Example API description*�example-operation2B
@
example-query��query��example-query description �R�
    Ê��stringBÇ��œ�
�200�”�
‘�
�OK�Š�
C
�application/json�/
-�+
)#/components/schemas/common.StatusMessage
C
�application/yaml�/
-�+
)#/components/schemas/common.StatusMessage�¥�
�400���
š�
�Bad Request�Š�
C
�application/json�/
-�+
)#/components/schemas/common.StatusMessage
C
�application/yaml�/
-�+
)#/components/schemas/common.StatusMessage*Y
W
U
�common.StatusMessage�=
;Ê��objectú�/
�
�message��
    ��string
�
�status��
    ��string

он генерирует следующий файл swagger:

openapi: 3.0.1
info:
  title: Example service
  description: Example service description
  contact:
    name: Example contact
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: "1.0"
servers:
- url: //localhost:9999/example/api/v1
paths:
  /exampleResource:
    get:
      summary: Example API
      description: Example API description
      operationId: example-operation
      parameters:
      - name: example-query
        in: query
        description: example-query description
        required: true
        schema:
          type: string
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
            application/yaml:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
        400:
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
            application/yaml:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
components:
  schemas:
    common.StatusMessage:
      type: object
      properties:
        message:
          type: string
        status:
          type: string

.pb может отображаться некорректно, откройте его здесь. Так что-то вроде:

�status��
    ��string

похоже:

<0x06>status<0x12><0x0b>
    Ê<0x01><0x06>string

Для примера выше я сначала написал спецификацию чванства, а затем сгенерировал .pb, но то же самое можно сделать и наоборот.

Текущее состояние:

Если у меня есть способ конвертировать файлы (.pb) и (.proto), цикл преобразования будет закрыт и завершен (.proto -> .pb -> .json/.yaml -> .pb -> .proto).

Я уверен, что должен быть способ добиться этого, и, следовательно, существует решение моей исходной проблемы. Но я не смог найти ни одной статьи или фрагмента кода, который бы это делал. Есть ли разумные способы взаимного преобразования файлов .pb и .proto?

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

Заранее спасибо!

Редактирует:

(1) Благодаря недавним комментариям становится ясно, что «преобразование» между .pb и .proto - это в первую очередь абсурдный вопрос. Но исходная проблема остается той же, то есть как сгенерировать спецификацию swagger3 (OpenAPI3) из файла protobuf (.proto), используя аннотации, теги или иным образом. Соответствующее изменение заголовка вопроса.

(2) Буквально на следующий день после того, как я разместил это, я наткнулся на репозиторий gnostic-grpc, описание которого говорит:

Этот инструмент преобразует описание API OpenAPI v3.0 в описание службы gRPC, которую можно использовать для реализации этого API с помощью перекодирования gRPC-JSON.

Опять же, это слишком рано заставило меня выйти. На самом деле, это был проект GSOC, и, как ни удивительна идея этого репозитория, он не выполняет требования. Более того, это не библиотека для взаимного преобразования, и она очень незрелая для любого производственного использования. Фактически, он не может предоставить некоторые из основных фундаментальных функций спецификации OpenAPI3.

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

(3) По-видимому, нет хороших и очевидных кандидатов для преобразования из .proto в спецификацию OpenAPI3 (.yaml/.json), за исключением gnostic- grpc, который очень незрелый и в настоящее время находится в стадии разработки для любого реального использования.

Но для обратного преобразования, то есть спецификации OpenAPI3 (.yaml/.json) в .proto, есть хорошая библиотека под названием openapi-generator в OpenAPITools, который преобразует спецификацию OpenAPI v2 / 3 в заглушки клиент / сервер почти для всех платформ. Но поскольку это не исходный вопрос, вопрос все еще остается открытым.


person Krishna Birla    schedule 21.04.2020    source источник
comment
Вы не конвертируете полезные данные protobuf вообще в .proto; это ничего не значит. Существует 2 формата protobuf: (a) двоичная кодировка protobuf - это то, что вы называете .pb в вопросе, и (b) самоуверенный вариант json, который выражает то же намерение в json; с этим контекстом (т.е. что .proto означает что-то совершенно другое), можете ли вы уточнить, что вы хотите здесь делать?   -  person Marc Gravell    schedule 21.04.2020
comment
Ох, ладно! Мой точный вариант использования - писать прото-файлы - ›генерировать сервер gRPC -› генерировать HTTPS-сервер, а также генерировать спецификации swagger для сервера. Я знаю, что это возможно для openAPI2 с использованием библиотеки grpc-gateway (которая использует аннотации в файле .proto), но ничего не могу найти для OpenAPI3. Я хочу преобразовать .proto в спецификацию OpenAPI3, используя аннотации, теги или что-то еще.   -  person Krishna Birla    schedule 21.04.2020
comment
У grpc-gateway в течение нескольких лет была проблема с поддержкой openAPI v3: github .com / grpc-architecture / grpc-gateway / issues / 441 Мне это тоже нужно. Может быть, мы могли бы поработать над этим вместе. Поскольку он уже генерирует openAPIv2, кажется, что подъем будет меньше, чем написание его с нуля.   -  person Clint    schedule 21.05.2020
comment
Я бы с удовольствием поработал над этим. В настоящее время я разрабатываю сценарии python для этого взаимного преобразования, и я буду использовать его с открытым исходным кодом, но более универсальное решение в более доступном репозитории будет гораздо более удивительным, и в любом случае сценарии python - это просто работа. Но что касается второй части, я думаю, что это определенно будет меньше работы, чем писать что-то с нуля, но все же много, и это хорошо! Это связано с тем, что OpenAPIv3 в значительной степени обратно несовместим.   -  person Krishna Birla    schedule 22.05.2020


Ответы (1)


Хотя ваше требование, похоже, состоит в том, чтобы получить спецификацию YAML (OpenAPNv3) от PROTO, вы можете проверить этот плагин - gnostic-grpc - для gnostic, который делает обратное, т.е. преобразует спецификацию YAML / JSON в прототип вместе с вызовами службы gRPC.

person Anupama Deshmukh    schedule 29.04.2020
comment
Да, я столкнулся с этим сразу после того, как разместил этот вопрос. Как ни удивительна идея этого репозитория, он еще не готов к использованию. Это был проект GSOC, в нем есть ошибки. И его преобразование одностороннее, как вы также сказали, и неполное. Он не поддерживает большинство конструкций openAPI, а те, которые он поддерживает, не используют возможности openAPI 3. Я пришел к выводу, что написать плагин - лучшее решение, это несложно. Вдобавок к этому я решил внести свой вклад в гностиков, потому что мне нравится эта идея. Это реальный вариант использования, для которого на удивление не существует решения. - person Krishna Birla; 30.04.2020
comment
Совершенно верно. Фактически, мы пытались использовать его и столкнулись с множеством ограничений из-за кажущейся неполной или частичной поддержки OpenAPI. Но, к сожалению, нет другой реализации, которая так близко подошла бы к получению proto (в частности, gRPC) из YAML, кроме этой, к сожалению. - person Anupama Deshmukh; 02.05.2020
comment
У меня также есть открытый вопрос на GitHub по тому же вопросу. - person Krishna Birla; 03.05.2020
comment
@AnupamaDeshmukh Я один из основных участников gnostic-grpc. Не могли бы вы подробнее рассказать, что вам не понравилось? Не стесняйтесь открывать вопросы в репозитории. - person LorenzHW; 20.06.2021