package main import ( "git.echinacities.com/mogfee/protoc-gen-kit/proto/v1/auth" "github.com/golang/protobuf/proto" "google.golang.org/genproto/googleapis/api/annotations" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/descriptorpb" "log" ) //go build && protoc --unknow_out=./proto --go_out=./proto/ --go-grpc_out=./proto proto/user.proto -I ./proto // protoc --unknow_out=./proto proto/user.proto func main() { u := &Kit{ imports: map[string]string{}, } protogen.Options{}.Run(u.Generate) } type Kit struct { imports map[string]string } func (u *Kit) addImports(imp string) { u.imports[imp] = imp } func (u *Kit) Generate(plugin *protogen.Plugin) error { if len(plugin.Files) < 1 { return nil } u.addImports("git.echinacities.com/mogfee/protoc-gen-kit/response") u.addImports("github.com/gin-gonic/gin") for _, f := range plugin.Files { if len(f.Services) == 0 { continue } //log.Println(f.Desc.Name()) fname := f.GeneratedFilenamePrefix + ".gin.go" t := plugin.NewGeneratedFile(fname, f.GoImportPath) t.P("package " + f.Desc.Name()) t.P("import (") for _, v := range u.imports { t.P(`"` + v + `"`) } t.P(")") t.P(`func NewGin(app *gin.Engine,srv UserServer) {`) for _, s := range f.Services { //t.P(`app.GET("/", func(c *gin.Context) {c.String(200, "ok")})`) for _, m := range s.Methods { method, path := u.getMethod(m) t.P(`_http_`, method, `_`, m.GoName, `(app, "`, path, `", srv)`) } } t.P(`}`) for _, s := range f.Services { log.Println(s.GoName) //t.P(`app.GET("/", func(c *gin.Context) {c.String(200, "ok")})`) for _, m := range s.Methods { method, _ := u.getMethod(m) switch method { case method_get: u.genGet(t, m) case method_post: u.genPost(t, m) case method_delete: u.genDelete(t, m) } //log.Println(m.Desc.Options().ProtoReflect().Get(annotations.E_Http).List()) //log.Println(m.Input.GoIdent.GoName) //log.Println(m.Input.Desc.Name()) //log.Println(m.Output.Desc.Name()) } } } return nil } func (Kit) genGet(t *protogen.GeneratedFile, m *protogen.Method) { t.P("func _http_", method_get, `_`, m.GoName, "(router *gin.Engine, method string, srv UserServer){") t.P(`router.`, method_get, `(method, func(c *gin.Context) { post := `, m.Input.GoIdent.GoName, `{} resp := response.New(c) if err := resp.BindQuery(&post); err != nil { resp.Error(err) return } result, err := srv.`, m.GoName, `(c, &post) if err != nil { resp.Error(err) return } c.JSON(200, result) })`) t.P("}") } func (Kit) genPost(t *protogen.GeneratedFile, m *protogen.Method) { t.P("func _http_", method_post, `_`, m.GoName, "(router *gin.Engine, method string, srv UserServer){") t.P(`router.`, method_post, `(method, func(c *gin.Context) { post := `, m.Input.GoIdent.GoName, `{} resp := response.New(c) if err := resp.BindJSON(&post); err != nil { resp.Error(err) return } result, err := srv.`, m.GoName, `(c, &post) if err != nil { resp.Error(err) return } c.JSON(200, result) })`) t.P("}") } func (Kit) genDelete(t *protogen.GeneratedFile, m *protogen.Method) { t.P("func _http_", method_delete, `_`, m.GoName, "(router *gin.Engine, method string, srv UserServer){") t.P(`router.`, method_delete, `(method, func(c *gin.Context) { post := `, m.Input.GoIdent.GoName, `{} resp := response.New(c) if err := resp.BindJSON(&post); err != nil { resp.Error(err) return } result, err := srv.`, m.GoName, `(c, &post) if err != nil { resp.Error(err) return } c.JSON(200, result) })`) t.P("}") } func (Kit) getAuth(m *protogen.Method) (bool, string) { if op, ok := m.Desc.Options().(*descriptorpb.MethodOptions); ok { if opts, err := proto.GetExtension(op, auth.E_Auth); err != nil { log.Println(err) } else { if vv, ok := opts.(*auth.AuthInfo); ok { return vv.Auth, vv.AuthKey } } } return false, "" } func (Kit) getMethod(m *protogen.Method) (method string, path string) { if op, ok := m.Desc.Options().(*descriptorpb.MethodOptions); ok { if opts, err := proto.GetExtension(op, annotations.E_Http); err != nil { log.Println(err) } else { if vv, ok := opts.(*annotations.HttpRule); ok { if vvv, ok := vv.Pattern.(*annotations.HttpRule_Get); ok { return method_get, vvv.Get } else if vvv, ok := vv.Pattern.(*annotations.HttpRule_Post); ok { return method_post, vvv.Post } else if vvv, ok := vv.Pattern.(*annotations.HttpRule_Delete); ok { return method_delete, vvv.Delete } } } } return "", "" } const ( method_get = "GET" method_post = "POST" method_delete = "DELETE" )