diff --git a/Makefile b/Makefile index c6a645e0ef7..6904a73407e 100644 --- a/Makefile +++ b/Makefile @@ -52,11 +52,13 @@ ifneq "$(GATEWAY_PLUGIN_FLAGS)" "" ADDITIONAL_FLAGS=,$(GATEWAY_PLUGIN_FLAGS) endif SWAGGER_EXAMPLES=examples/examplepb/echo_service.proto \ - examples/examplepb/a_bit_of_everything.proto + examples/examplepb/a_bit_of_everything.proto \ + examples/examplepb/wrappers.proto EXAMPLES=examples/examplepb/echo_service.proto \ examples/examplepb/a_bit_of_everything.proto \ examples/examplepb/stream.proto \ - examples/examplepb/flow_combination.proto + examples/examplepb/flow_combination.proto \ + examples/examplepb/wrappers.proto EXAMPLE_SVCSRCS=$(EXAMPLES:.proto=.pb.go) EXAMPLE_GWSRCS=$(EXAMPLES:.proto=.pb.gw.go) EXAMPLE_SWAGGERSRCS=$(EXAMPLES:.proto=.swagger.json) diff --git a/examples/examplepb/echo_service.pb.go b/examples/examplepb/echo_service.pb.go index 0cca760395b..8a600f8dcd3 100644 --- a/examples/examplepb/echo_service.pb.go +++ b/examples/examplepb/echo_service.pb.go @@ -14,6 +14,7 @@ It is generated from these files: examples/examplepb/a_bit_of_everything.proto examples/examplepb/stream.proto examples/examplepb/flow_combination.proto + examples/examplepb/wrappers.proto It has these top-level messages: SimpleMessage @@ -25,6 +26,7 @@ It has these top-level messages: UnaryProto NestedProto SingleNestedProto + Wrappers */ package examplepb diff --git a/examples/examplepb/wrappers.pb.go b/examples/examplepb/wrappers.pb.go new file mode 100644 index 00000000000..62268e17c2e --- /dev/null +++ b/examples/examplepb/wrappers.pb.go @@ -0,0 +1,179 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: examples/examplepb/wrappers.proto + +package examplepb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf5 "github.com/golang/protobuf/ptypes/wrappers" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type Wrappers struct { + StringValue *google_protobuf5.StringValue `protobuf:"bytes,1,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` + Int32Value *google_protobuf5.Int32Value `protobuf:"bytes,2,opt,name=int32_value,json=int32Value" json:"int32_value,omitempty"` + Int64Value *google_protobuf5.Int64Value `protobuf:"bytes,3,opt,name=int64_value,json=int64Value" json:"int64_value,omitempty"` + FloatValue *google_protobuf5.FloatValue `protobuf:"bytes,4,opt,name=float_value,json=floatValue" json:"float_value,omitempty"` + DoubleValue *google_protobuf5.DoubleValue `protobuf:"bytes,5,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` + BoolValue *google_protobuf5.BoolValue `protobuf:"bytes,6,opt,name=bool_value,json=boolValue" json:"bool_value,omitempty"` +} + +func (m *Wrappers) Reset() { *m = Wrappers{} } +func (m *Wrappers) String() string { return proto.CompactTextString(m) } +func (*Wrappers) ProtoMessage() {} +func (*Wrappers) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } + +func (m *Wrappers) GetStringValue() *google_protobuf5.StringValue { + if m != nil { + return m.StringValue + } + return nil +} + +func (m *Wrappers) GetInt32Value() *google_protobuf5.Int32Value { + if m != nil { + return m.Int32Value + } + return nil +} + +func (m *Wrappers) GetInt64Value() *google_protobuf5.Int64Value { + if m != nil { + return m.Int64Value + } + return nil +} + +func (m *Wrappers) GetFloatValue() *google_protobuf5.FloatValue { + if m != nil { + return m.FloatValue + } + return nil +} + +func (m *Wrappers) GetDoubleValue() *google_protobuf5.DoubleValue { + if m != nil { + return m.DoubleValue + } + return nil +} + +func (m *Wrappers) GetBoolValue() *google_protobuf5.BoolValue { + if m != nil { + return m.BoolValue + } + return nil +} + +func init() { + proto.RegisterType((*Wrappers)(nil), "grpc.gateway.examples.examplepb.Wrappers") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for WrappersService service + +type WrappersServiceClient interface { + Create(ctx context.Context, in *Wrappers, opts ...grpc.CallOption) (*Wrappers, error) +} + +type wrappersServiceClient struct { + cc *grpc.ClientConn +} + +func NewWrappersServiceClient(cc *grpc.ClientConn) WrappersServiceClient { + return &wrappersServiceClient{cc} +} + +func (c *wrappersServiceClient) Create(ctx context.Context, in *Wrappers, opts ...grpc.CallOption) (*Wrappers, error) { + out := new(Wrappers) + err := grpc.Invoke(ctx, "/grpc.gateway.examples.examplepb.WrappersService/Create", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for WrappersService service + +type WrappersServiceServer interface { + Create(context.Context, *Wrappers) (*Wrappers, error) +} + +func RegisterWrappersServiceServer(s *grpc.Server, srv WrappersServiceServer) { + s.RegisterService(&_WrappersService_serviceDesc, srv) +} + +func _WrappersService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Wrappers) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WrappersServiceServer).Create(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.gateway.examples.examplepb.WrappersService/Create", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WrappersServiceServer).Create(ctx, req.(*Wrappers)) + } + return interceptor(ctx, in, info, handler) +} + +var _WrappersService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.gateway.examples.examplepb.WrappersService", + HandlerType: (*WrappersServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Create", + Handler: _WrappersService_Create_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "examples/examplepb/wrappers.proto", +} + +func init() { proto.RegisterFile("examples/examplepb/wrappers.proto", fileDescriptor4) } + +var fileDescriptor4 = []byte{ + // 330 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0xd2, 0xc1, 0x4a, 0x33, 0x31, + 0x10, 0x07, 0x70, 0xb6, 0xfd, 0xbe, 0x62, 0xb3, 0x82, 0xb0, 0x78, 0xd0, 0xb5, 0x58, 0xed, 0x49, + 0x3d, 0x64, 0xb1, 0x2d, 0x05, 0x45, 0x10, 0xaa, 0x08, 0x5e, 0x2d, 0x28, 0x78, 0x91, 0xa4, 0x4d, + 0x97, 0x40, 0xdc, 0x09, 0xd9, 0xb4, 0xd5, 0x93, 0xe8, 0x23, 0xe8, 0xa3, 0xf9, 0x0a, 0x3e, 0x88, + 0x6c, 0x3a, 0xd9, 0x82, 0xa5, 0xe8, 0x6d, 0x66, 0xf7, 0xff, 0x1b, 0x18, 0x32, 0x64, 0x5f, 0x3c, + 0xb1, 0x47, 0xad, 0x44, 0x9e, 0x60, 0xa1, 0x79, 0x32, 0x33, 0x4c, 0x6b, 0x61, 0x72, 0xaa, 0x0d, + 0x58, 0x88, 0x9a, 0xa9, 0xd1, 0x43, 0x9a, 0x32, 0x2b, 0x66, 0xec, 0x99, 0xfa, 0x3c, 0x2d, 0xf3, + 0x71, 0x23, 0x05, 0x48, 0x95, 0x48, 0x98, 0x96, 0x09, 0xcb, 0x32, 0xb0, 0xcc, 0x4a, 0xc8, 0x90, + 0xc7, 0xbb, 0xf8, 0xd7, 0x75, 0x7c, 0x32, 0xfe, 0x31, 0xbe, 0xf5, 0x5a, 0x25, 0x6b, 0x77, 0xf8, + 0x29, 0x3a, 0x27, 0xeb, 0xb9, 0x35, 0x32, 0x4b, 0x1f, 0xa6, 0x4c, 0x4d, 0xc4, 0x56, 0xb0, 0x17, + 0x1c, 0x84, 0xed, 0x06, 0x9d, 0xcf, 0xa0, 0x7e, 0x06, 0x1d, 0xb8, 0xd0, 0x6d, 0x91, 0xb9, 0x09, + 0xf3, 0x45, 0x13, 0x9d, 0x91, 0x50, 0x66, 0xb6, 0xd3, 0x46, 0x5f, 0x71, 0x7e, 0x67, 0xc9, 0x5f, + 0x17, 0x99, 0x39, 0x27, 0xb2, 0xac, 0x51, 0xf7, 0xba, 0xa8, 0xab, 0xab, 0x75, 0xaf, 0xbb, 0xd0, + 0x58, 0x17, 0x7a, 0xac, 0x80, 0x59, 0xd4, 0xff, 0x56, 0xe8, 0xab, 0x22, 0x83, 0x7a, 0x5c, 0xd6, + 0xc5, 0xea, 0x23, 0x98, 0x70, 0x25, 0x90, 0xff, 0x5f, 0xb1, 0xfa, 0xa5, 0x0b, 0xe1, 0xea, 0xa3, + 0x45, 0x13, 0x9d, 0x10, 0xc2, 0x01, 0x14, 0xf2, 0x9a, 0xe3, 0xf1, 0x12, 0xef, 0x03, 0xa8, 0x39, + 0xae, 0x73, 0x5f, 0xb6, 0xdf, 0x03, 0xb2, 0xe1, 0xdf, 0x60, 0x20, 0xcc, 0x54, 0x0e, 0x45, 0xf4, + 0x42, 0x6a, 0x17, 0x46, 0x30, 0x2b, 0xa2, 0x43, 0xfa, 0xcb, 0x05, 0x50, 0x6f, 0xe3, 0xbf, 0x47, + 0x5b, 0xcd, 0xb7, 0xcf, 0xaf, 0x8f, 0xca, 0x76, 0x6b, 0x33, 0x99, 0x1e, 0xfb, 0xe3, 0x2b, 0x6f, + 0xe3, 0x34, 0x38, 0xea, 0x87, 0xf7, 0xf5, 0x92, 0xf1, 0x9a, 0x5b, 0xa0, 0xf3, 0x1d, 0x00, 0x00, + 0xff, 0xff, 0x03, 0xd1, 0x02, 0x94, 0xb0, 0x02, 0x00, 0x00, +} diff --git a/examples/examplepb/wrappers.pb.gw.go b/examples/examplepb/wrappers.pb.gw.go new file mode 100644 index 00000000000..bd57b237e34 --- /dev/null +++ b/examples/examplepb/wrappers.pb.gw.go @@ -0,0 +1,122 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: examples/examplepb/wrappers.proto + +/* +Package examplepb is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package examplepb + +import ( + "io" + "net/http" + + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray + +func request_WrappersService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client WrappersServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq Wrappers + var metadata runtime.ServerMetadata + + if req.ContentLength > 0 { + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + } + + msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +// RegisterWrappersServiceHandlerFromEndpoint is same as RegisterWrappersServiceHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterWrappersServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterWrappersServiceHandler(ctx, mux, conn) +} + +// RegisterWrappersServiceHandler registers the http handlers for service WrappersService to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterWrappersServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterWrappersServiceHandlerClient(ctx, mux, NewWrappersServiceClient(conn)) +} + +// RegisterWrappersServiceHandler registers the http handlers for service WrappersService to "mux". +// The handlers forward requests to the grpc endpoint over the given implementation of "WrappersServiceClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "WrappersServiceClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "WrappersServiceClient" to call the correct interceptors. +func RegisterWrappersServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client WrappersServiceClient) error { + + mux.Handle("POST", pattern_WrappersService_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_WrappersService_Create_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_WrappersService_Create_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_WrappersService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "example", "wrappers"}, "")) +) + +var ( + forward_WrappersService_Create_0 = runtime.ForwardResponseMessage +) diff --git a/examples/examplepb/wrappers.proto b/examples/examplepb/wrappers.proto new file mode 100644 index 00000000000..094b0a4c662 --- /dev/null +++ b/examples/examplepb/wrappers.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +option go_package = "examplepb"; +package grpc.gateway.examples.examplepb; + +import "google/api/annotations.proto"; +import "google/protobuf/wrappers.proto"; + +message Wrappers { + google.protobuf.StringValue string_value = 1; + google.protobuf.Int32Value int32_value = 2; + google.protobuf.Int64Value int64_value = 3; + google.protobuf.FloatValue float_value = 4; + google.protobuf.DoubleValue double_value = 5; + google.protobuf.BoolValue bool_value = 6; +} + +service WrappersService { + rpc Create(Wrappers) returns (Wrappers) { + option (google.api.http) = { + post: "/v1/example/wrappers" + body: "*" + }; + } +} diff --git a/examples/examplepb/wrappers.swagger.json b/examples/examplepb/wrappers.swagger.json new file mode 100644 index 00000000000..01fd9d2e6a9 --- /dev/null +++ b/examples/examplepb/wrappers.swagger.json @@ -0,0 +1,75 @@ +{ + "swagger": "2.0", + "info": { + "title": "examples/examplepb/wrappers.proto", + "version": "version not set" + }, + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/v1/example/wrappers": { + "post": { + "operationId": "Create", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/examplepbWrappers" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/examplepbWrappers" + } + } + ], + "tags": [ + "WrappersService" + ] + } + } + }, + "definitions": { + "examplepbWrappers": { + "type": "object", + "properties": { + "string_value": { + "type": "string" + }, + "int32_value": { + "type": "integer", + "format": "int32" + }, + "int64_value": { + "type": "integer", + "format": "int64" + }, + "float_value": { + "type": "number", + "format": "float" + }, + "double_value": { + "type": "number", + "format": "double" + }, + "bool_value": { + "type": "boolean", + "format": "boolean" + } + } + } + } +} diff --git a/protoc-gen-swagger/genswagger/template.go b/protoc-gen-swagger/genswagger/template.go index c838a5808d7..7b3dd05d7fb 100644 --- a/protoc-gen-swagger/genswagger/template.go +++ b/protoc-gen-swagger/genswagger/template.go @@ -201,6 +201,18 @@ func renderMessagesAsDefinition(messages messageMap, d swaggerDefinitionsObject, continue case ".google.protobuf.Duration": continue + case ".google.protobuf.StringValue": + continue + case ".google.protobuf.Int32Value": + continue + case ".google.protobuf.Int64Value": + continue + case ".google.protobuf.FloatValue": + continue + case ".google.protobuf.DoubleValue": + continue + case ".google.protobuf.BoolValue": + continue } if opt := msg.GetOptions(); opt != nil && opt.MapEntry != nil && *opt.MapEntry { continue