Example #1
0
// 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)
}
Example #2
0
// 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
}
Example #3
0
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
}
Example #4
0
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()
	}
}
Example #5
0
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)
	}
}
Example #6
0
func (g *svcauth) generateDesc(servName string, method *pb.MethodDescriptorProto, authMethod *authMethod, interfaceMethods *[]string) {
	emittedCaller := false
	if authMethod != nil && authMethod.Authn != nil {
		var (
			inputType, _    = g.gen.ObjectNamed(method.GetInputType()).(*generator.Descriptor)
			callerType      = g.lookupMessageType(inputType, authMethod.Authn.Caller)
			shortCallerType = toShort(callerType)
		)

		g.P(`Strategies: []string{`)
		for _, s := range authMethod.Authn.Strategies {
			g.P(strconv.Quote(s), `,`)
		}
		g.P(`},`)

		emittedCaller = true
		g.P(`CallerType: ((*`, callerType, `)(nil)),`)
		g.P(`GetCaller: func(msg interface{}) interface{} {`)
		g.P(`var (`)
		g.P(`input = msg.(*`, g.typeName(method.GetInputType()), `)`)
		g.P(`caller *`, callerType)
		g.P(`)`)
		g.getMessage(inputType, authMethod.Authn.Caller, "input", "caller", true)
		g.P(`if caller == nil {`)
		g.P(`caller = &`, callerType, `{}`)
		g.P(`}`)
		g.P(`return caller`)
		g.P(`},`)
		g.P(`SetCaller: func(msg interface{}, v interface{}) {`)
		g.P(`var (`)
		g.P(`input = msg.(*`, g.typeName(method.GetInputType()), `)`)
		g.P(`caller = v.(*`, callerType, `)`)
		g.P(`)`)
		g.setMessage(inputType, authMethod.Authn.Caller, "input", "caller", true)
		g.P(`},`)
		g.P(`Authenticate: func(h interface{}, ctx context.Context, strategies []string, c interface{}) error {`)
		g.P(`return h.(`, servName, `ServerAuth).AuthenticateAs`, shortCallerType, `(ctx, strategies, c.(*`, callerType, `))`)
		g.P(`},`)

		*interfaceMethods = append(*interfaceMethods,
			fmt.Sprintf("AuthenticateAs%s(%s.Context, []string, *%s) error", shortCallerType, g.contextPkg.Use(), callerType))
	}
	if authMethod != nil && authMethod.Authz != nil {
		var (
			inputType, _    = g.gen.ObjectNamed(method.GetInputType()).(*generator.Descriptor)
			callerType      = g.lookupMessageType(inputType, authMethod.Authz.Caller)
			shortCallerType = toShort(callerType)
			// AuthorizeCallerForCertificateRef(ctx golang_org_x_net_context.Context, scope string, caller *Caller, context *CertificateRef) error
			authzCallName = "Authorize" + shortCallerType
			authzCallArgs = "ctx, scope, caller.(*" + callerType + ")"
			authzDeclArgs = g.contextPkg.Use() + ".Context, string, *" + callerType
		)

		if !emittedCaller {
			g.P(`CallerType: ((*`, callerType, `)(nil)),`)
			g.P(`GetCaller: func(msg interface{}) interface{} {`)
			g.P(`var (`)
			g.P(`input = msg.(*`, g.typeName(method.GetInputType()), `)`)
			g.P(`caller *`, callerType)
			g.P(`)`)
			g.getMessage(inputType, authMethod.Authz.Caller, "input", "caller", true)
			g.P(`if caller == nil {`)
			g.P(`caller = &`, callerType, `{}`)
			g.P(`}`)
			g.P(`return caller`)
			g.P(`},`)
		}

		g.P(`Scope: `, strconv.Quote(authMethod.Authz.Scope), `,`)

		if authMethod.Authz.Context != "" {
			var (
				contextType      = g.lookupMessageType(inputType, authMethod.Authz.Context)
				shortContextType = toShort(contextType)
			)
			authzCallName += "For" + shortContextType
			authzCallArgs += ", context.(*" + contextType + ")"
			authzDeclArgs += ", *" + contextType

			g.P(`ContextType: ((*`, contextType, `)(nil)),`)
			g.P(`GetContext: func(msg interface{}) interface{} {`)
			g.P(`var (`)
			g.P(`input = msg.(*`, g.typeName(method.GetInputType()), `)`)
			g.P(`context *`, contextType)
			g.P(`)`)
			g.getMessage(inputType, authMethod.Authz.Context, "input", "context", true)
			g.P(`return context`)
			g.P(`},`)
		}

		g.P(`Authorize: func(h interface{}, ctx context.Context, scope string, caller, context interface{}) error {`)
		g.P(`return h.(`, servName, `ServerAuth).`, authzCallName, `(`, authzCallArgs, `)`)
		g.P(`},`)

		*interfaceMethods = append(*interfaceMethods,
			fmt.Sprintf("%s(%s) error", authzCallName, authzDeclArgs))
	}
}