Skip to content

Commit

Permalink
WIP: Use a proto option to describe whether a Swagger Operation is de…
Browse files Browse the repository at this point in the history
…precated.

Issues:
- This change breaks tests, uses possibly inappropriate package names etc.
- 'deprecated' status of an operation should be determined by whether the proto
  method has been declared deprecated.
- Previous way of declaring extra values using JSON prefixed with "OpenAPI: "
  in the comments has not been removed.
- Extension for Swagger options has an arbitrary, but almost certainly wrong,
  identifier assigned to it.
- Neither global API properties nor the main useful property on a swagger
  Operation, "externalDocs", are supported with this new method.
- As a possible idea, we may want to support raw JSON in an option as well.
  • Loading branch information
ivucica committed Mar 7, 2017
1 parent d091216 commit acce01c
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 2 deletions.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ OUTPUT_DIR=_output
RUNTIME_PROTO=runtime/internal/stream_chunk.proto
RUNTIME_GO=$(RUNTIME_PROTO:.proto=.pb.go)

SWAGGER_PROTO=protoc-gen-swagger/options/swagger.proto protoc-gen-swagger/options/annotations.proto
SWAGGER_GO=$(SWAGGER_PROTO:.proto=.pb.go)

PKGMAP=Mgoogle/protobuf/descriptor.proto=$(GO_PLUGIN_PKG)/descriptor,Mgoogle/api/annotations.proto=$(PKG)/$(GOOGLEAPIS_DIR)/google/api,Mexamples/sub/message.proto=$(PKG)/examples/sub
ADDITIONAL_FLAGS=
ifneq "$(GATEWAY_PLUGIN_FLAGS)" ""
Expand Down Expand Up @@ -94,10 +97,13 @@ $(OPTIONS_GO): $(OPTIONS_PROTO) $(GO_PLUGIN)
$(RUNTIME_GO): $(RUNTIME_PROTO) $(GO_PLUGIN)
protoc -I $(PROTOC_INC_PATH) --plugin=$(GO_PLUGIN) -I. --go_out=$(PKGMAP):. $(RUNTIME_PROTO)

$(SWAGGER_GO): $(SWAGGER_PROTO) $(GO_PLUGIN)
protoc -I $(PROTOC_INC_PATH) --plugin=$(GO_PLUGIN) -I. --go_out=$(PKGMAP):. $(SWAGGER_PROTO)

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

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

$(EXAMPLE_SVCSRCS): $(GO_PLUGIN) $(EXAMPLES)
Expand All @@ -120,7 +126,7 @@ $(ABE_EXAMPLE_SRCS): $(ABE_EXAMPLE_SPEC)
-l go -o examples/clients --additional-properties packageName=abe
@rm -f $(EXAMPLE_CLIENT_DIR)/README.md $(EXAMPLE_CLIENT_DIR)/git_push.sh $(EXAMPLE_CLIENT_DIR)/.gitignore

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 Down
30 changes: 30 additions & 0 deletions protoc-gen-swagger/genswagger/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (

pbdescriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
swagger_options "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options"
"github.com/golang/protobuf/proto"
)

var swaggerExtrasRegexp = regexp.MustCompile(`(?s)^(.*[^\s])[\s]*<!-- swagger extras start(.*)swagger extras end -->[\s]*(.*)$`)
Expand Down Expand Up @@ -531,6 +533,34 @@ func renderServices(services []*descriptor.Service, paths swaggerPathsObject, re
panic(err)
}

extractOperationOptions := func (meth *pbdescriptor.MethodDescriptorProto) (*swagger_options.Operation, error) {
if meth.Options == nil {
return nil, nil
}
if !proto.HasExtension(meth.Options, swagger_options.E_SwaggerOperation) {
return nil, nil
}
ext, err := proto.GetExtension(meth.Options, swagger_options.E_SwaggerOperation)
if err != nil {
return nil, err
}
opts, ok := ext.(*swagger_options.Operation)
if !ok {
return nil, fmt.Errorf("extension is %T; want an Operation", ext)
}
return opts, nil
}
opts, err := extractOperationOptions(meth.MethodDescriptorProto)
if opts != nil {
if err != nil {
panic(err)
}
// TODO(ivucica): this would be better supported by looking whether the method is deprecated in the proto file
operationObject.Deprecated = opts.Deprecated

// TODO(ivucica): add remaining fields of operation object
}

switch b.HTTPMethod {
case "DELETE":
pathItemObject.Delete = operationObject
Expand Down
1 change: 1 addition & 0 deletions protoc-gen-swagger/genswagger/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type swaggerOperationObject struct {
Responses swaggerResponsesObject `json:"responses"`
Parameters swaggerParametersObject `json:"parameters,omitempty"`
Tags []string `json:"tags,omitempty"`
Deprecated bool `json:"deprecated,omitempty"`

ExternalDocs *swaggerExternalDocumentationObject `json:"externalDocs,omitempty"`
}
Expand Down
10 changes: 10 additions & 0 deletions protoc-gen-swagger/options/annotations.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto3";

package grpc_gateway.protoc_gen_swagger.options;

import "protoc-gen-swagger/options/swagger.proto";
import "google/protobuf/descriptor.proto";

extend google.protobuf.MethodOptions {
Operation swagger_operation = 123456789; // TODO(ivucica): how to determine ID?
}
35 changes: 35 additions & 0 deletions protoc-gen-swagger/options/swagger.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
syntax = "proto3";

package grpc_gateway.protoc_gen_swagger.options;

// `Operation` is a representation of Swagger specification's Operation object.
//
// See: http://swagger.io/specification/#operation-object-36
//
// TODO(ivucica): document fields
message Operation {
repeated string tags = 1;
string summary = 2;
string description = 3;
ExternalDocumentation external_docs = 4;
string operation_id = 5;
repeated string consumes = 6;
repeated string produces = 7;
// field 8 is reserved for 'parameters'.
// field 9 is reserved for 'responses'.
repeated string schemes = 10;
bool deprecated = 11;
// field 12 is reserved for 'security'.

}

// `ExternalDocumentation` is a representation of Swagger specification's
// ExternalDocumentation object.
//
// See: http://swagger.io/specification/#external-documentation-object-40
//
// TODO(ivucica): document fields
message ExternalDocumentation {
string description = 1;
string url = 2;
}

0 comments on commit acce01c

Please sign in to comment.