Search code examples
gohttpswaggerprotocol-buffersgrpc

Having shared swagger (openapi) type definitions alongside with protobuf ones


In my project, I have both gRPC and HTTP endpoints, they have swagger and proto definitions respectively. Now, the problem that I have is that swagger and proto definitions have shared types, for example, consider those two hypothetical definitions:

swagger.yaml

...
paths:
  /users:
    get:
      summary: get list of all 
      responses:
        '200':
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: 'shared.yaml#/components/schemas/User'
...

protobuf.proto

...
message User {
    ...
}

message GetUsersReply {
    repeated User list = 1;
}

service MyGrpcService {
    rpc GetUsers (GetUsersRequest) returns (GetUsersReply) {}
}
...

In this example, I have a User entity, however, it is defined in both places (shared.yaml and protobuf.proto) which is quite inconvenient, as to in order to change User definition I'd have to change them in both specifications, both places simultaneously, which from my experience, will most definitely lead to unexpected crashed, build fails, etc. I'm looking for a solution that will help me build my application well, production-ready, if you will. Admittedly, I haven't got as much production experience to have an understanding or knowledge with this scenario type, for which I'm asking here, to help me guide in the right direction.

I have several thoughts which might help me resolve this issue, those are:

  1. Write myself a utility, which will just solve this issue. However, I feel like I'm not the first to discover this problem, and I must miss some obvious solution here.
  2. Use third party solution here, here or here. But I feel like those were either abandoned or do not do the quite thing I'm interested in.

For this question being more specific, I'm using golang to build micro-services.


Solution

  • So after some more research, I've decided to use grpc-gateway, pointed out by @DazWilkin. The reason I thought it was irrelevant to my question, was the fact that it wraps gRPC endpoints with HTTP+JSON, but as it turns out, the repo has a dedicated option to only generate the swagger (OpenAPI v2).

    In my final vote I've actually decided to go with a gRPC/HTTP gateway for my project with these two simple reasons:

    1. It makes the code more clean and unified
    2. The project I'm working on realistically won't have a reason to ditch or change the underlaying technologies