Skip to content

Commit

Permalink
Merge pull request grpc-ecosystem#156 from t-yuki/swagger_descriptions
Browse files Browse the repository at this point in the history
Generate Swagger description for service methods using proto comments.
  • Loading branch information
yugui committed May 17, 2016
2 parents 91cfe0c + 18263a9 commit 40c372f
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 63 deletions.
17 changes: 17 additions & 0 deletions examples/examplepb/echo_service.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions examples/examplepb/echo_service.proto
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
syntax = "proto3";
option go_package = "examplepb";

// Echo Service
//
// Echo Service API consists of a single service which returns
// a message.
package gengo.grpc.gateway.examples.examplepb;

import "google/api/annotations.proto";

// SimpleMessage represents a simple message sent to the Echo service.
message SimpleMessage {
// Id represents the message identifier.
string id = 1;
}

// Echo service responds to incoming echo requests.
service EchoService {
// Echo method receives a simple message and returns it.
//
// The message posted as the id parameter will also be
// returned.
rpc Echo(SimpleMessage) returns (SimpleMessage) {
option (google.api.http) = {
post: "/v1/example/echo/{id}"
};
}
// EchoBody method receives a simple message and returns it.
rpc EchoBody(SimpleMessage) returns (SimpleMessage) {
option (google.api.http) = {
post: "/v1/example/echo_body"
Expand Down
20 changes: 12 additions & 8 deletions examples/examplepb/echo_service.swagger.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"swagger": "2.0",
"info": {
"version": "",
"title": ""
"title": "Echo Service",
"description": "Echo Service API consists of a single service which returns\na message.",
"version": "version not set"
},
"schemes": [
"http",
Expand All @@ -17,10 +18,11 @@
"paths": {
"/v1/example/echo/{id}": {
"post": {
"summary": "EchoService.Echo",
"summary": "Echo method receives a simple message and returns it.",
"description": "The message posted as the id parameter will also be\nreturned.",
"operationId": "Echo",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbSimpleMessage"
Expand All @@ -43,10 +45,10 @@
},
"/v1/example/echo_body": {
"post": {
"summary": "EchoService.EchoBody",
"summary": "EchoBody method receives a simple message and returns it.",
"operationId": "EchoBody",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbSimpleMessage"
Expand Down Expand Up @@ -75,9 +77,11 @@
"properties": {
"id": {
"type": "string",
"format": "string"
"format": "string",
"description": "Id represents the message identifier."
}
}
},
"description": "SimpleMessage represents a simple message sent to the Echo service."
}
}
}
9 changes: 9 additions & 0 deletions examples/examplepb/streamless_everything.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ import "examples/sub/message.proto";
// Intentionaly complicated message type to cover much features of Protobuf.
// NEXT ID: 27
message ABitOfEverything {
// Nested is nested type.
message Nested {
// name is nested field.
string name = 1;
uint32 amount = 2;
// DeepEnum is one or zero.
enum DeepEnum {
// FALSE is false.
FALSE = 0;
// TRUE is true.
TRUE = 1;
}
DeepEnum ok = 3;
Expand Down Expand Up @@ -54,11 +59,15 @@ message EmptyMessage {
}

message IdMessage {
// uuid is UUID value
string uuid = 1;
}

// NumericEnum is one or zero.
enum NumericEnum {
// ZERO means 0
ZERO = 0;
// ONE means 1
ONE = 1;
}

Expand Down
55 changes: 26 additions & 29 deletions examples/examplepb/streamless_everything.swagger.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"swagger": "2.0",
"info": {
"version": "",
"title": ""
"title": "examples/examplepb/streamless_everything.proto",
"version": "version not set"
},
"schemes": [
"http",
Expand All @@ -17,10 +17,9 @@
"paths": {
"/v1/example/a_bit_of_everything": {
"get": {
"summary": "ABitOfEverythingService.List",
"operationId": "List",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbABitOfEverything"
Expand All @@ -32,10 +31,9 @@
]
},
"post": {
"summary": "ABitOfEverythingService.CreateBody",
"operationId": "CreateBody",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbABitOfEverything"
Expand All @@ -59,10 +57,9 @@
},
"/v1/example/a_bit_of_everything/bulk": {
"post": {
"summary": "ABitOfEverythingService.BulkCreate",
"operationId": "BulkCreate",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbEmptyMessage"
Expand All @@ -86,10 +83,9 @@
},
"/v1/example/a_bit_of_everything/echo": {
"post": {
"summary": "ABitOfEverythingService.BulkEcho",
"operationId": "BulkEcho",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/subStringMessage"
Expand All @@ -113,10 +109,9 @@
},
"/v1/example/a_bit_of_everything/echo/{value}": {
"get": {
"summary": "ABitOfEverythingService.Echo",
"operationId": "Echo",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/subStringMessage"
Expand All @@ -139,10 +134,9 @@
},
"/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}": {
"post": {
"summary": "ABitOfEverythingService.Create",
"operationId": "Create",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbABitOfEverything"
Expand Down Expand Up @@ -263,10 +257,9 @@
},
"/v1/example/a_bit_of_everything/{single_nested.name}": {
"post": {
"summary": "ABitOfEverythingService.DeepPathEcho",
"operationId": "DeepPathEcho",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbABitOfEverything"
Expand Down Expand Up @@ -297,10 +290,9 @@
},
"/v1/example/a_bit_of_everything/{uuid}": {
"get": {
"summary": "ABitOfEverythingService.Lookup",
"operationId": "Lookup",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbABitOfEverything"
Expand All @@ -321,10 +313,9 @@
]
},
"delete": {
"summary": "ABitOfEverythingService.Delete",
"operationId": "Delete",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbEmptyMessage"
Expand All @@ -345,10 +336,9 @@
]
},
"put": {
"summary": "ABitOfEverythingService.Update",
"operationId": "Update",
"responses": {
"default": {
"200": {
"description": "Description",
"schema": {
"$ref": "#/definitions/examplepbEmptyMessage"
Expand Down Expand Up @@ -388,20 +378,23 @@
},
"name": {
"type": "string",
"format": "string"
"format": "string",
"description": "name is nested field."
},
"ok": {
"$ref": "#/definitions/NestedDeepEnum"
}
}
},
"description": "Nested is nested type."
},
"NestedDeepEnum": {
"type": "string",
"enum": [
"FALSE",
"TRUE"
],
"default": "FALSE"
"default": "FALSE",
"description": "DeepEnum is one or zero.\n\n - FALSE: FALSE is false.\n - TRUE: TRUE is true."
},
"examplepbABitOfEverything": {
"type": "object",
Expand Down Expand Up @@ -505,7 +498,8 @@
},
"uint32_value": {
"type": "integer",
"format": "int64"
"format": "int64",
"title": "TODO(yugui) add bytes_value"
},
"uint64_value": {
"type": "integer",
Expand All @@ -515,7 +509,8 @@
"type": "string",
"format": "string"
}
}
},
"title": "Intentionaly complicated message type to cover much features of Protobuf.\nNEXT ID: 27"
},
"examplepbEmptyMessage": {
"type": "object"
Expand All @@ -525,7 +520,8 @@
"properties": {
"uuid": {
"type": "string",
"format": "string"
"format": "string",
"title": "uuid is UUID value"
}
}
},
Expand All @@ -535,7 +531,8 @@
"ZERO",
"ONE"
],
"default": "ZERO"
"default": "ZERO",
"description": "NumericEnum is one or zero.\n\n - ZERO: ZERO means 0\n - ONE: ONE means 1"
},
"subStringMessage": {
"type": "object",
Expand Down
6 changes: 4 additions & 2 deletions protoc-gen-grpc-gateway/descriptor/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,12 @@ func (r *Registry) loadFile(file *descriptor.FileDescriptorProto) {
}

func (r *Registry) registerMsg(file *File, outerPath []string, msgs []*descriptor.DescriptorProto) {
for _, md := range msgs {
for i, md := range msgs {
m := &Message{
File: file,
Outers: outerPath,
DescriptorProto: md,
Index: i,
}
for _, fd := range md.GetField() {
m.Fields = append(m.Fields, &Field{
Expand All @@ -124,11 +125,12 @@ func (r *Registry) registerMsg(file *File, outerPath []string, msgs []*descripto
}

func (r *Registry) registerEnum(file *File, outerPath []string, enums []*descriptor.EnumDescriptorProto) {
for _, ed := range enums {
for i, ed := range enums {
e := &Enum{
File: file,
Outers: outerPath,
EnumDescriptorProto: ed,
Index: i,
}
file.Enums = append(file.Enums, e)
r.enums[e.FQEN()] = e
Expand Down
Loading

0 comments on commit 40c372f

Please sign in to comment.