// generateClientSignature returns the client-side signature for a method. func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string { origMethName := method.GetName() methName := generator.CamelCase(origMethName) if reservedClientName[methName] { methName += "_" } reqArg := ", in *" + g.typeName(method.GetInputType()) if method.GetClientStreaming() { reqArg = "" } respName := "*" + g.typeName(method.GetOutputType()) if method.GetServerStreaming() || method.GetClientStreaming() { respName = servName + "_" + generator.CamelCase(origMethName) + "Client" } return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName) }
// generateServerSignature returns the server-side signature for a method. func (g *svcauth) generateServerCall(servName string, method *pb.MethodDescriptorProto) string { origMethName := method.GetName() methName := generator.CamelCase(origMethName) if reservedClientName[methName] { methName += "_" } var reqArgs []string if !method.GetServerStreaming() && !method.GetClientStreaming() { reqArgs = append(reqArgs, "ctx") } if !method.GetClientStreaming() { reqArgs = append(reqArgs, "input") } if method.GetServerStreaming() || method.GetClientStreaming() { reqArgs = append(reqArgs, "stream") } return methName + "(" + strings.Join(reqArgs, ", ") + ") " }
// generateServerSignature returns the server-side signature for a method. func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string { origMethName := method.GetName() methName := generator.CamelCase(origMethName) if reservedClientName[methName] { methName += "_" } var reqArgs []string ret := "error" if !method.GetServerStreaming() && !method.GetClientStreaming() { reqArgs = append(reqArgs, contextPkg+".Context") ret = "(*" + g.typeName(method.GetOutputType()) + ", error)" } if !method.GetClientStreaming() { reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType())) } if method.GetServerStreaming() || method.GetClientStreaming() { reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server") } return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret }
func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string { methName := generator.CamelCase(method.GetName()) hname := fmt.Sprintf("_%s_%s_Handler", servName, methName) inType := g.typeName(method.GetInputType()) outType := g.typeName(method.GetOutputType()) if !method.GetServerStreaming() && !method.GetClientStreaming() { g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {") g.P("in := new(", inType, ")") g.P("if err := dec(in); err != nil { return nil, err }") g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }") g.P("info := &", grpcPkg, ".UnaryServerInfo{") g.P("Server: srv,") g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",") g.P("}") g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {") g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))") g.P("}") g.P("return interceptor(ctx, in, info, handler)") g.P("}") g.P() return hname } streamType := unexport(servName) + methName + "Server" g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {") if !method.GetClientStreaming() { g.P("m := new(", inType, ")") g.P("if err := stream.RecvMsg(m); err != nil { return err }") g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})") } else { g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})") } g.P("}") g.P() genSend := method.GetServerStreaming() genSendAndClose := !method.GetServerStreaming() genRecv := method.GetClientStreaming() // Stream auxiliary types and methods. g.P("type ", servName, "_", methName, "Server interface {") if genSend { g.P("Send(*", outType, ") error") } if genSendAndClose { g.P("SendAndClose(*", outType, ") error") } if genRecv { g.P("Recv() (*", inType, ", error)") } g.P(grpcPkg, ".ServerStream") g.P("}") g.P() g.P("type ", streamType, " struct {") g.P(grpcPkg, ".ServerStream") g.P("}") g.P() if genSend { g.P("func (x *", streamType, ") Send(m *", outType, ") error {") g.P("return x.ServerStream.SendMsg(m)") g.P("}") g.P() } if genSendAndClose { g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {") g.P("return x.ServerStream.SendMsg(m)") g.P("}") g.P() } if genRecv { g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {") g.P("m := new(", inType, ")") g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }") g.P("return m, nil") g.P("}") g.P() } return hname }
func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) { sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName()) methName := generator.CamelCase(method.GetName()) inType := g.typeName(method.GetInputType()) outType := g.typeName(method.GetOutputType()) g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{") if !method.GetServerStreaming() && !method.GetClientStreaming() { g.P("out := new(", outType, ")") // TODO: Pass descExpr to Invoke. g.P("err := ", grpcPkg, `.Invoke(ctx, "`, sname, `", in, out, c.cc, opts...)`) g.P("if err != nil { return nil, err }") g.P("return out, nil") g.P("}") g.P() return } streamType := unexport(servName) + methName + "Client" g.P("stream, err := ", grpcPkg, ".NewClientStream(ctx, ", descExpr, `, c.cc, "`, sname, `", opts...)`) g.P("if err != nil { return nil, err }") g.P("x := &", streamType, "{stream}") if !method.GetClientStreaming() { g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }") g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") } g.P("return x, nil") g.P("}") g.P() genSend := method.GetClientStreaming() genRecv := method.GetServerStreaming() genCloseAndRecv := !method.GetServerStreaming() // Stream auxiliary types and methods. g.P("type ", servName, "_", methName, "Client interface {") if genSend { g.P("Send(*", inType, ") error") } if genRecv { g.P("Recv() (*", outType, ", error)") } if genCloseAndRecv { g.P("CloseAndRecv() (*", outType, ", error)") } g.P(grpcPkg, ".ClientStream") g.P("}") g.P() g.P("type ", streamType, " struct {") g.P(grpcPkg, ".ClientStream") g.P("}") g.P() if genSend { g.P("func (x *", streamType, ") Send(m *", inType, ") error {") g.P("return x.ClientStream.SendMsg(m)") g.P("}") g.P() } if genRecv { g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {") g.P("m := new(", outType, ")") g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") g.P("return m, nil") g.P("}") g.P() } if genCloseAndRecv { g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {") g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") g.P("m := new(", outType, ")") g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") g.P("return m, nil") g.P("}") g.P() } }
func (g *jsonschema) generateServiceMethodSchema(file *generator.FileDescriptor, srv *pb.ServiceDescriptorProto, meth *pb.MethodDescriptorProto, rule *limbo.HttpRule, comment string) { var ( method string pattern string ) switch p := rule.GetPattern().(type) { case *limbo.HttpRule_Delete: method = "DELETE" pattern = p.Delete case *limbo.HttpRule_Get: method = "GET" pattern = p.Get case *limbo.HttpRule_Post: method = "POST" pattern = p.Post case *limbo.HttpRule_Patch: method = "PATCH" pattern = p.Patch case *limbo.HttpRule_Put: method = "PUT" pattern = p.Put default: panic("unknown pattern type") } query := "" if idx := strings.IndexByte(pattern, '?'); idx >= 0 { query = pattern[idx+1:] pattern = pattern[:idx] } path := regexp.MustCompile("\\{.+\\}").ReplaceAllStringFunc(pattern, func(v string) string { return strings.Replace(v, ".", "_", -1) }) input := strings.TrimPrefix(meth.GetInputType(), ".") output := strings.TrimPrefix(meth.GetOutputType(), ".") var outputSchema interface{} = map[string]string{"$ref": output} if meth.GetServerStreaming() { outputSchema = map[string]interface{}{ "type": "array", "items": outputSchema, } } var tags = []string{srv.GetName()} tags = append(tags, rule.Tags...) op := map[string]interface{}{ "tags": tags, "description": comment, "responses": map[string]interface{}{ "200": map[string]interface{}{ "description": "", "schema": outputSchema, }, }, } var parameters []map[string]interface{} if params := g.collectPathParameters(pattern); len(params) > 0 { parameters = append(parameters, params...) } if params := g.collectQueryParameters(query); len(params) > 0 { parameters = append(parameters, params...) } if method != "HEAD" && method != "GET" && method != "OPTIONS" && method != "DELETE" { parameters = append(parameters, map[string]interface{}{ "name": "parameters", "in": "body", "schema": map[string]interface{}{ "$ref": input, }, }) } if len(parameters) > 0 { op["parameters"] = parameters } if scope, ok := limbo.GetScope(meth); ok { op["security"] = []map[string][]string{ {"oauth": {scope}}, } } decl := &operationDecl{ Pattern: path, Method: method, Dependencies: uniqStrings([]string{input, output}), Swagger: op, } g.operations = append(g.operations, decl) // x, _ := json.MarshalIndent(op, " ", " ") // fmt.Fprintf(os.Stderr, "%s %s:\n %s\n", method, path, x) for _, a := range rule.GetAlternatives() { g.generateServiceMethodSchema(file, srv, meth, a, comment) } }