我原来的用例:
我正在使用gRPC
服务器(使用protobuf
)在 GO 中构建应用程序,并将其包装在 HTTPS 服务器中(使用gin
)。只有 HTTPS 服务器被发布到客户端以供使用(我的意思是我的应用程序可以通过 REST API 访问,然后实际上在 gRPC 端点上拨号),我使用Swagger
OpenAPI3 发布它(版本 3 是主要的这里的要求)规范。gRPC 和 HTTPS 都是必需的,任何解决方案都应遵循此架构。
我不想在两个地方维护我的服务器规范,即我不想同时维护 proto 文件 ( .proto
) 和 swagger 规范 ( .json/.yaml
)。由于我绝对必须编写 proto 文件来生成 gRPC 服务器,因此我想自动化 swagger 规范生成 (OpenAPI3)。
我在哪里:
我可以使用grpc-gateway库swagger
从 protobuf 文件 () 生成 OpenAPI2 规范,如下所示: grpc-rest-go-example。但我的要求是 OpenAPI3;更具体地说,我想使用OpenAPI3 中的功能并从proto 的功能映射到它。这在 OpenAPI2 中是不可能的,因为它不允许 API 具有多个类型定义的请求/响应主体,这是 OpenAPI3 通过启用 oneOf、anyOf 和 allOf 构造添加的功能。.proto
oneOf
oneof
在尝试这样做时,我偶然发现了 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 规范转换为几乎所有平台的客户端/服务器存根。但由于这不是最初的问题,所以问题仍然悬而未决。