11

我原来的用例:

我正在使用gRPC服务器(使用protobuf)在 GO 中构建应用程序,并将其包装在 HTTPS 服务器中(使用gin)。只有 HTTPS 服务器被发布到客户端以供使用(我的意思是我的应用程序可以通过 REST API 访问,然后实际上在 gRPC 端点上拨号),我使用SwaggerOpenAPI3 发布它(版本 3 是主要的这里的要求)规范。gRPC 和 HTTPS 都是必需的,任何解决方案都应遵循此架构。

我不想在两个地方维护我的服务器规范,即我不想同时维护 proto 文件 ( .proto) 和 swagger 规范 ( .json/.yaml)。由于我绝对必须编写 proto 文件来生成 gRPC 服务器,因此我想自动化 swagger 规范生成 (OpenAPI3)。

我在哪里:

我可以使用grpc-gatewayswagger从 protobuf 文件 () 生成 OpenAPI2 规范,如下所示: grpc-rest-go-example。但我的要求是 OpenAPI3;更具体地说,我想使用OpenAPI3 中的功能并从proto 的功能映射到它。这在 OpenAPI2 中是不可能的,因为它不允许 API 具有多个类型定义的请求/响应主体,这是 OpenAPI3 通过启用 oneOf、anyOf 和 allOf 构造添加的功能。.protooneOfoneof

在尝试这样做时,我偶然发现了 GoogleAPIs googleapis/ gnostic 的这个库,它的描述是:

此存储库包含一个 Go 命令行工具,可将 JSON 和 YAML OpenAPI 描述与等效的协议缓冲区表示形式相互转换。

乍一看,这似乎完全解决了我的问题,但事实证明,这个库只在协议缓冲区 (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

它生成以下招摇文件:

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

对于上面的示例,我首先编写了 swagger 规范,然后生成了.pb同样的方法,但反过来也可以。

当前状态:

如果我有办法在 ( .pb) 和 ( .proto) 文件之间进行转换,则转换循环将关闭并完成 ( .proto-> .pb-> .json/.yaml-> .pb-> .proto)。

我确信必须有一种方法来实现这一点,因此我的原始问题存在解决方案。但是我找不到任何可以做到这一点的文章或代码。是否有健全的方法可以在文件之间进行相互.pb转换.proto

如果您对我的原始用例有完全不同的解决方案,也请随时分享。这会有很大帮助。

提前致谢!

编辑:

(1) 感谢最近的评论,很明显,在.pb和之间进行“转换”.proto首先是一个荒谬的问题。但最初的问题仍然存在,即如何.proto使用注释、标签或其他方式从 protobuf 文件 () 生成 swagger3 (OpenAPI3) 规范。相应地更改问题标题。

(2) 就在我发布这篇文章的第二天,我碰到了gnostic-grpc存储库,其中的描述说:

此工具将 OpenAPI v3.0 API 描述转换为 gRPC 服务的描述,该服务可用于使用 gRPC-JSON 转码实现该 API。

同样,这让我过早退出。实际上,这是一个 GSOC 项目,尽管这个存储库的想法令人惊叹,但它并不能满足要求。此外,这不是一个相互转换的库,对于任何生产用途都非常不成熟。事实上,它未能提供 OpenAPI3 规范的一些基本特性。

但是这个存储库正朝着正确的方向前进。我的结论是有一个自定义插件可以做到这一点,主要是通过扩展 GO 中的注释库。

(3) 显然,除了gnostic-grpc还非常不成熟,并且正在为任何类型的实际用途进行大量工作之外,没有好的和明显的候选者可以转换.proto为 OpenAPI3 规范 ( )。.yaml/.json

但是对于反向转换,即 OpenAPI3 spec ( .yaml/.json) to .proto,在 OpenAPITools 下有一个名为openapi-generator的好库,它可以将 OpenAPI v2/3 规范转换为几乎所有平台的客户端/服务器存根。但由于这不是最初的问题,所以问题仍然悬而未决。

4

1 回答 1

1

虽然,您的要求似乎是从 PROTO 获取 YAML (OpenAPNv3) 规范,但您可以签出这个插件 - gnostic-grpc - 用于 gnostic,它执行相反的操作,即从 YAML/JSON 规范转换为 proto 以及 gRPC 服务来电。

于 2020-04-29T08:12:39.630 回答