Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/NYTimes/openapi2proto

A tool for generating Protobuf v3 schemas and gRPC service definitions from OpenAPI specifications
https://github.com/NYTimes/openapi2proto

Last synced: 3 months ago
JSON representation

A tool for generating Protobuf v3 schemas and gRPC service definitions from OpenAPI specifications

Awesome Lists containing this project

README

        

# openapi2proto [![Build Status](https://travis-ci.org/nytimes/openapi2proto.svg?branch=master)](https://travis-ci.org/nytimes/openapi2proto)

This tool will accept an OpenAPI/Swagger definition (yaml or JSON) and generate a Protobuf v3 schema and gRPC service definition from it.

## Install

To install, have Go installed with `$GOPATH/bin` on your `$PATH` and then:
```
go install github.com/NYTimes/openapi2proto/cmd/openapi2proto@latest
```

On Older versions of Go (<1.15), use:
```
go get -u github.com/NYTimes/openapi2proto/cmd/openapi2proto
```

## Run

There are some CLI flags for using the tool:
* `-spec` to point to the appropriate OpenAPI spec file
* `-annotate` to include (google.api.http options) for [grpc-gateway](https://github.com/gengo/grpc-gateway) users. This is disabled by default.
* `-out` to have the output written to a file rather than `Stdout`. Defaults to `Stdout` if this is not specified.
* `-indent` to override the default indentation for Protobuf specs of 4 spaces.
* `-skip-rpcs` to skip generation of rpcs. These are generated by default.
* `-skip-deprecated-rpcs` to skip generation of rpcs for endpoints marked as deprecated. This is disabled by default.
* `-namespace-enums` to enable inserting the enum name as an enum prefix for each value. This is disabled by default.
* `-add-autogenerated-comment` to add comment on top of the generated protos that those files are autogenerated and should not be modified. This is disabled by default.

## Protobuf Tags
* To allow for more control over how your protobuf schema evolves, all parameters and property definitions will accept an optional extension parameter, `x-proto-tag`, that will overide the generated tag with the value supplied.

## External Files
* Any externally referenced Open API spec will be fetched and inlined.
* Any externally referenced Protobuf files will be added as imports.
* Example usage: `$ref: "google/protobuf/timestamp.proto#/google.protobuf.Timestamp"`

## Global Options

Protocol Buffer options such as package names are supported via `x-global-options` key.

```yaml
x-global-options:
go_package: myawesomepackage
```

Will generate:

```protobuf
option go_package = "myawesomepackage"
```

## Extensions

Global extensions may be generated by specifying `x-extensions` key.

```yaml
x-extensions:
- base: google.protobuf.MethodOptions
fields:
- name: role
type: string
number: 50001
- name: visibility
type: string
number: 50002
- name: timeout
type: int32
number: 50003
```

Will generate:

```protobuf
extend google.protobuf.MethodOptions {
string role = 50001;
string visibility = 50002;
int32 timeout = 50003;
}
```

Nested extensions are currently not supported.

## Method Options

Method options may be generated by specifying the `x-options` key within each method.

```yaml
paths:
/foo
post:
x-options:
bar: baz
```

Will generate:

```protobuf
rpc foo(...) returns (...) {
option (bar) = "baz";
}
```

## Caveats

* Fields with scalar types that can also be "null" will get wrapped with one of the `google.protobuf.*Value` types.
* Fields with that have more than 1 type and the second type is not "null" will be replaced with the `google.protobuf.Any` type.
* Endpoints that respond with an array will be wrapped with a message type that has a single field, 'items', that contains the array.
* Only "200" and "201" responses are inspected for determining the expected return value for RPC endpoints.
* To prevent enum collisions and to match the [protobuf style guide](https://developers.google.com/protocol-buffers/docs/style#enums), enum values will be `CAPITALS_WITH_UNDERSCORES` and nested enum values will have their parent types prepended to their names.

## Example

```
╰─➤ openapi2proto -spec swagger.yaml -annotate
syntax = "proto3";

package swaggerpetstore;

import "google/api/annotations.proto";
import "google/protobuf/empty.proto";

message AddPetRequest {
message PetMessage {
int64 id = 1;
string name = 2;
string tag = 3;
}

// Pet to add to the store
PetMessage pet = 1;
}

message AddPetResponse {
int64 id = 1;
string name = 2;
string tag = 3;
}

message DeletePetRequest {
// ID of pet to delete
int64 id = 1;
}

message FindPetByIdRequest {
// ID of pet to fetch
int64 id = 1;
}

message FindPetByIdResponse {
int64 id = 1;
string name = 2;
string tag = 3;
}

message FindPetsByIdsRequest {
repeated string ids = 1;

// maximum number of results to return
int32 limit = 2;
}

message FindPetsByIdsResponse {
message PetsMessage {
int64 id = 1;
string name = 2;
string tag = 3;
}

repeated PetsMessage pets = 1;
}

message FindPetsRequest {
// maximum number of results to return
int32 limit = 1;

// tags to filter by
repeated string tags = 2;
}

message FindPetsResponse {
message PetsMessage {
int64 id = 1;
string name = 2;
string tag = 3;
}

repeated PetsMessage pets = 1;
}

service SwaggerPetstoreService {
// Creates a new pet in the store. Duplicates are allowed
rpc AddPet(AddPetRequest) returns (AddPetResponse) {
option (google.api.http) = {
post: "/api/pets"
body: "pet"
};
}

// deletes a single pet based on the ID supplied
rpc DeletePet(DeletePetRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
delete: "/api/pets/{id}"
};
}

// Returns a user based on a single ID, if the user does not have access to the pet
rpc FindPetById(FindPetByIdRequest) returns (FindPetByIdResponse) {
option (google.api.http) = {
get: "/api/pets/{id}"
};
}

// Returns all pets from the system that the user has access to
rpc FindPets(FindPetsRequest) returns (FindPetsResponse) {
option (google.api.http) = {
get: "/api/pets"
};
}

// Returns all pets from the system that the user has access to
rpc FindPetsByIds(FindPetsByIdsRequest) returns (FindPetsByIdsResponse) {
option (google.api.http) = {
get: "/api/pets/{ids}"
};
}
}
```