Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add custom options to allow more control of swagger/openapi output #145

Merged
merged 26 commits into from
Nov 3, 2017
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6ff06d8
Apply additional Swagger properties using JSON.
ivucica May 7, 2016
fcc2dca
Swagger: Replaced '<!-- ... -->' for raw JSON with last paragraph 'Sw…
ivucica May 7, 2016
20a6d40
Change from 'Swagger: ' to 'OpenAPI: ' prefix.
ivucica May 7, 2016
321663d
WIP: Use a proto option to describe whether a Swagger Operation is de…
ivucica Feb 13, 2017
7043966
WIP: Setting API properties through an option.
ivucica Mar 7, 2017
cdc1094
WIP: Correctly reserve fields. Update link. TODO: merge with commit M…
ivucica Oct 27, 2017
41b436f
WIP: Refer to the specification as OpenAPI v2, not Swagger.
ivucica Oct 27, 2017
74cd394
WIP: Clean up after OpenAPIv2 options proto generation.
ivucica Oct 27, 2017
549ccee
WIP: JSON is disappearing from the output protos.
ivucica Oct 27, 2017
6b2b321
WIP: Fix typo 'want an Swagger' -> 'want a Swagger object'.
ivucica Oct 27, 2017
db4a056
WIP: Process all remaining fields of the OpenAPI v2 Swagger object.
ivucica Oct 27, 2017
7697bcf
WIP: ExternalDocs belongs on OpenAPIv2's Swagger object, not on the I…
ivucica Oct 27, 2017
162c375
WIP: Remove use of JSON. Introduce schema and tag object. Support ext…
ivucica Oct 28, 2017
b53579c
WIP: Add built annotations.pb.go and openapiv2.pb.go.
ivucica Oct 28, 2017
60d116f
WIP: go fmt on protoc-gen-swagger.
ivucica Oct 28, 2017
d509096
WIP: Provide a more unique operation ID in case of additional bindings.
ivucica Oct 28, 2017
3949620
WIP: Try to fix integration test by removing 'host' from the Swagger …
ivucica Oct 28, 2017
a386e97
WIP: Remove swaggerExtrasRegexp.
ivucica Oct 29, 2017
290f777
WIP: Move error checking for extractSchemaOptionFromMessageDescriptor…
ivucica Oct 29, 2017
97ee19b
WIP: Fix typo: 'want a Schema'.
ivucica Oct 29, 2017
ceb4c4e
Assign IDs for proto options extensions.
ivucica Nov 1, 2017
099fda5
Move test definitions for options-based extension to Swagger output f…
ivucica Nov 1, 2017
d7b0ba4
Undo commenting out dependency on EXAMPLE_CLIENT_SRCS.
ivucica Nov 2, 2017
d7a9a69
Change the proto package to start with 'grpc.gateway', as seems to be…
ivucica Nov 2, 2017
84c3046
Add a comment about all IDs being ok to be the same.
ivucica Nov 2, 2017
a543b9e
Regenerated Swagger-generated clients.
ivucica Nov 2, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ OUTPUT_DIR=_output
RUNTIME_PROTO=runtime/internal/stream_chunk.proto
RUNTIME_GO=$(RUNTIME_PROTO:.proto=.pb.go)

OPENAPIV2_PROTO=protoc-gen-swagger/options/openapiv2.proto protoc-gen-swagger/options/annotations.proto
OPENAPIV2_GO=$(OPENAPIV2_PROTO:.proto=.pb.go)

PKGMAP=Mgoogle/protobuf/descriptor.proto=$(GO_PLUGIN_PKG)/descriptor,Mexamples/sub/message.proto=$(PKG)/examples/sub
ADDITIONAL_FLAGS=
ifneq "$(GATEWAY_PLUGIN_FLAGS)" ""
Expand Down Expand Up @@ -83,17 +86,20 @@ generate: $(RUNTIME_GO)

.SUFFIXES: .go .proto

$(GO_PLUGIN):
$(GO_PLUGIN):
go get $(GO_PLUGIN_PKG)
go build -o $@ $(GO_PLUGIN_PKG)

$(RUNTIME_GO): $(RUNTIME_PROTO) $(GO_PLUGIN)
protoc -I $(PROTOC_INC_PATH) --plugin=$(GO_PLUGIN) -I. --go_out=$(PKGMAP):. $(RUNTIME_PROTO)

$(OPENAPIV2_GO): $(OPENAPIV2_PROTO) $(GO_PLUGIN)
protoc -I $(PROTOC_INC_PATH) --plugin=$(GO_PLUGIN) -I. --go_out=$(PKGMAP):$(GOPATH)/src $(OPENAPIV2_PROTO)

$(GATEWAY_PLUGIN): $(RUNTIME_GO) $(GATEWAY_PLUGIN_SRC)
go build -o $@ $(GATEWAY_PLUGIN_PKG)

$(SWAGGER_PLUGIN): $(SWAGGER_PLUGIN_SRC)
$(SWAGGER_PLUGIN): $(SWAGGER_PLUGIN_SRC) $(OPENAPIV2_GO)
go build -o $@ $(SWAGGER_PLUGIN_PKG)

$(EXAMPLE_SVCSRCS): $(GO_PLUGIN) $(EXAMPLES)
Expand All @@ -120,7 +126,7 @@ $(ABE_EXAMPLE_SRCS): $(ABE_EXAMPLE_SPEC)
$(EXAMPLE_CLIENT_DIR)/abe/git_push.sh \
$(EXAMPLE_CLIENT_DIR)/abe/.travis.yml

examples: $(EXAMPLE_SVCSRCS) $(EXAMPLE_GWSRCS) $(EXAMPLE_DEPSRCS) $(EXAMPLE_SWAGGERSRCS) $(EXAMPLE_CLIENT_SRCS)
examples: $(EXAMPLE_SVCSRCS) $(EXAMPLE_GWSRCS) $(EXAMPLE_DEPSRCS) $(EXAMPLE_SWAGGERSRCS) #$(EXAMPLE_CLIENT_SRCS)
test: examples
go test -race $(PKG)/...

Expand All @@ -143,5 +149,6 @@ realclean: distclean
rm -f $(GO_PLUGIN)
rm -f $(SWAGGER_PLUGIN)
rm -f $(EXAMPLE_CLIENT_SRCS)
rm -f $(OPENAPIV2_GO)

.PHONY: generate examples test lint clean distclean realclean
199 changes: 116 additions & 83 deletions examples/examplepb/a_bit_of_everything.pb.go

Large diffs are not rendered by default.

64 changes: 64 additions & 0 deletions examples/examplepb/a_bit_of_everything.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,43 @@ import "google/protobuf/duration.proto";
import "examples/sub/message.proto";
import "examples/sub2/message.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-swagger/options/annotations.proto";

option (grpc_gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you need to import the relevant proto file to access options?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's annotations.proto, I see. I was confused by the package here, importing from protoc-gen-swagger and then accessing a grpc_gateway namespace. Might just be me but feels like a disconnect?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My approach for setting proto package name:

  • this is the grpc_gateway project, and users may want some more uniqueness -> grpc_gateway
  • this project contains generators protoc-gen-grpc-gateway and protoc-gen-swagger; this only applies to the latter -> protoc_gen_swagger
  • these are option protos extending the proto descriptors a bit -> options

I'm not sure why I did not go for a fully global namespace com.github.grpc_ecosystem.grpc_gateway..... Either way there's a variety of approaches taken.

You did get me to look around so I will change this to use grpc.gateway, as that seems to be used for the runtime and example protos.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me :)

info: {
title: "A Bit of Everything";
version: "1.0";
contact: {
name: "gRPC-Gateway project";
url: "https://github.com/grpc-ecosystem/grpc-gateway";
email: "none@example.com";
};
};
// Overwriting host entry breaks tests, so this is not done here.
external_docs: {
url: "https://github.com/grpc-ecosystem/grpc-gateway";
description: "More about gRPC-Gateway";
}
schemes: HTTP;
schemes: HTTPS;
schemes: WSS;
consumes: "application/json";
consumes: "application/x-foo-mime";
produces: "application/json";
produces: "application/x-foo-mime";
};


// Intentionaly complicated message type to cover much features of Protobuf.
// NEXT ID: 27
message ABitOfEverything {
option (grpc_gateway.protoc_gen_swagger.options.openapiv2_schema) = {
external_docs: {
url: "https://github.com/grpc-ecosystem/grpc-gateway";
description: "Find out more about ABitOfEverything";
}
};

// Nested is nested type.
message Nested {
// name is nested field.
Expand Down Expand Up @@ -72,7 +105,18 @@ enum NumericEnum {
ONE = 1;
}

// ABitOfEverything service is used to validate that APIs with complicated
// proto messages and URL templates are still processed correctly.
service ABitOfEverythingService {

option (grpc_gateway.protoc_gen_swagger.options.openapiv2_tag) = {
description: "ABitOfEverythingService description -- which should not be used in place of the documentation comment!"
external_docs: {
url: "https://github.com/grpc-ecosystem/grpc-gateway";
description: "Find out more about EchoService";
}
};

rpc Create(ABitOfEverything) returns (ABitOfEverything) {
// TODO add enum_value
option (google.api.http) = {
Expand Down Expand Up @@ -105,7 +149,21 @@ service ABitOfEverythingService {
option (google.api.http) = {
get: "/v1/example/a_bit_of_everything/query/{uuid}"
};
option (grpc_gateway.protoc_gen_swagger.options.openapiv2_operation) = {
deprecated: true // For testing purposes.
external_docs: {
url: "https://github.com/grpc-ecosystem/grpc-gateway";
description: "Find out more about GetQuery";
}
};
}
// Echo allows posting a StringMessage value.
//
// It also exposes multiple bindings.
//
// This makes it useful when validating that the OpenAPI v2 API
// description exposes documentation correctly on all paths
// defined as additional_bindings in the proto.
rpc Echo(grpc.gateway.examples.sub.StringMessage) returns (grpc.gateway.examples.sub.StringMessage) {
option (google.api.http) = {
get: "/v1/example/a_bit_of_everything/echo/{value}"
Expand All @@ -117,6 +175,12 @@ service ABitOfEverythingService {
get: "/v2/example/echo"
}
};
option (grpc_gateway.protoc_gen_swagger.options.openapiv2_operation) = {
external_docs: {
url: "https://github.com/grpc-ecosystem/grpc-gateway";
description: "Find out more Echo";
}
};
}
rpc DeepPathEcho(ABitOfEverything) returns (ABitOfEverything) {
option (google.api.http) = {
Expand Down
63 changes: 51 additions & 12 deletions examples/examplepb/a_bit_of_everything.swagger.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
{
"swagger": "2.0",
"info": {
"title": "examples/examplepb/a_bit_of_everything.proto",
"version": "version not set"
"title": "A Bit of Everything",
"version": "1.0",
"contact": {
"name": "gRPC-Gateway project",
"url": "https://github.com/grpc-ecosystem/grpc-gateway",
"email": "none@example.com"
}
},
"schemes": [
"http",
"https"
"https",
"wss"
],
"consumes": [
"application/json"
"application/json",
"application/x-foo-mime"
],
"produces": [
"application/json"
"application/json",
"application/x-foo-mime"
],
"paths": {
"/v1/example/a_bit_of_everything": {
Expand Down Expand Up @@ -43,6 +51,8 @@
},
"/v1/example/a_bit_of_everything/echo/{value}": {
"get": {
"summary": "Echo allows posting a StringMessage value.",
"description": "It also exposes multiple bindings.\n\nThis makes it useful when validating that the OpenAPI v2 API\ndescription exposes documentation correctly on all paths\ndefined as additional_bindings in the proto.",
"operationId": "Echo",
"responses": {
"200": {
Expand All @@ -62,7 +72,11 @@
],
"tags": [
"ABitOfEverythingService"
]
],
"externalDocs": {
"description": "Find out more Echo",
"url": "https://github.com/grpc-ecosystem/grpc-gateway"
}
}
},
"/v1/example/a_bit_of_everything/query/{uuid}": {
Expand Down Expand Up @@ -264,7 +278,12 @@
],
"tags": [
"ABitOfEverythingService"
]
],
"deprecated": true,
"externalDocs": {
"description": "Find out more about GetQuery",
"url": "https://github.com/grpc-ecosystem/grpc-gateway"
}
}
},
"/v1/example/a_bit_of_everything/{float_value}/{double_value}/{int64_value}/separator/{uint64_value}/{int32_value}/{fixed64_value}/{fixed32_value}/{bool_value}/{string_value}/{uint32_value}/{sfixed32_value}/{sfixed64_value}/{sint32_value}/{sint64_value}/{nonConventionalNameValue}": {
Expand Down Expand Up @@ -498,7 +517,9 @@
},
"/v2/example/echo": {
"get": {
"operationId": "Echo",
"summary": "Echo allows posting a StringMessage value.",
"description": "It also exposes multiple bindings.\n\nThis makes it useful when validating that the OpenAPI v2 API\ndescription exposes documentation correctly on all paths\ndefined as additional_bindings in the proto.",
"operationId": "Echo3",
"responses": {
"200": {
"description": "",
Expand All @@ -517,10 +538,16 @@
],
"tags": [
"ABitOfEverythingService"
]
],
"externalDocs": {
"description": "Find out more Echo",
"url": "https://github.com/grpc-ecosystem/grpc-gateway"
}
},
"post": {
"operationId": "Echo",
"summary": "Echo allows posting a StringMessage value.",
"description": "It also exposes multiple bindings.\n\nThis makes it useful when validating that the OpenAPI v2 API\ndescription exposes documentation correctly on all paths\ndefined as additional_bindings in the proto.",
"operationId": "Echo2",
"responses": {
"200": {
"description": "",
Expand All @@ -541,7 +568,11 @@
],
"tags": [
"ABitOfEverythingService"
]
],
"externalDocs": {
"description": "Find out more Echo",
"url": "https://github.com/grpc-ecosystem/grpc-gateway"
}
}
},
"/v2/example/timeout": {
Expand Down Expand Up @@ -707,7 +738,11 @@
"title": "repeated enum value. it is comma-separated in query"
}
},
"title": "Intentionaly complicated message type to cover much features of Protobuf.\nNEXT ID: 27"
"title": "Intentionaly complicated message type to cover much features of Protobuf.\nNEXT ID: 27",
"externalDocs": {
"description": "Find out more about ABitOfEverything",
"url": "https://github.com/grpc-ecosystem/grpc-gateway"
}
},
"examplepbNumericEnum": {
"type": "string",
Expand All @@ -731,5 +766,9 @@
}
}
}
},
"externalDocs": {
"description": "More about gRPC-Gateway",
"url": "https://github.com/grpc-ecosystem/grpc-gateway"
}
}
2 changes: 1 addition & 1 deletion examples/examplepb/echo_service.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"get": {
"summary": "Echo method receives a simple message and returns it.",
"description": "The message posted as the id parameter will also be\nreturned.",
"operationId": "Echo",
"operationId": "Echo2",
"responses": {
"200": {
"description": "",
Expand Down
Loading