From 25c38491fe738eed34766969fc89eff35ee5a149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=BC=9F=E4=B9=90?= Date: Mon, 20 Feb 2023 15:53:41 +0800 Subject: [PATCH] x --- app.log | 0 demo/main.go | 78 +++++++++++++++++++++++++++++ example/main.go | 28 +++++++++-- example/service/service.go | 12 ++--- go.mod | 5 +- go.sum | 7 +++ main.go | 80 +++++++++++++++++++----------- middleware/add_header_md.go | 26 ++++++++++ middleware/jwt.go | 25 ++++++++++ middleware/logger.go | 41 +++++++++++++++ middleware/middleware.go | 34 +++++++++++++ middleware/recover.go | 20 ++++++++ middleware/validate.go | 23 +++++++++ proto/auth/auth.proto | 2 +- proto/v1/user.gin.go | 45 +++++++++++------ response/response.go | 46 +++++------------ response/json.go => xjson/xjson.go | 15 +++--- xlog/xlog.go | 19 +++++++ xstring/xstring.go | 17 +++++++ xuser/xuser.go | 20 ++++++++ 20 files changed, 448 insertions(+), 95 deletions(-) create mode 100644 app.log create mode 100644 demo/main.go create mode 100644 middleware/add_header_md.go create mode 100644 middleware/jwt.go create mode 100644 middleware/logger.go create mode 100644 middleware/middleware.go create mode 100644 middleware/recover.go create mode 100644 middleware/validate.go rename response/json.go => xjson/xjson.go (84%) create mode 100644 xlog/xlog.go create mode 100644 xstring/xstring.go create mode 100644 xuser/xuser.go diff --git a/app.log b/app.log new file mode 100644 index 0000000..e69de29 diff --git a/demo/main.go b/demo/main.go new file mode 100644 index 0000000..c26fe0f --- /dev/null +++ b/demo/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "context" + "fmt" + "github.com/gorilla/mux" + "log" + "net/http" +) + +type FilterFunc func(http.Handler) http.Handler + +func FilterChain(filters ...FilterFunc) FilterFunc { + return func(next http.Handler) http.Handler { + for i := len(filters) - 1; i >= 0; i-- { + next = filters[i](next) + } + return next + } +} + +type Context struct { + context.Context + req *http.Request + res http.ResponseWriter +} + +func (c *Context) String(code int, str string) error { + c.res.WriteHeader(code) + _, err := c.res.Write([]byte(str)) + return err +} + +func (c *Context) Result(code int, str string) error { + c.res.WriteHeader(code) + _, err := c.res.Write([]byte(str)) + return err +} + +type HandleFunc func(Context) error + +func IndexPage(ctx Context) error { + //return errors.New("xxx") + return ctx.String(200, "hello index") +} +func Logger() HandleFunc { + return func(c Context) error { + return nil + } +} + +func main() { + app := mux.NewRouter() + next := http.Handler(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + ctx := Context{ + res: res, + req: req, + } + h := Logger() + h(ctx) + if err := IndexPage(ctx); err != nil { + ctx.Result(500, "err:"+err.Error()) + } + })) + next = FilterChain(func(handler http.Handler) http.Handler { + return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + fmt.Println("start") + handler.ServeHTTP(writer, request) + fmt.Println("end") + }) + })(next) + app.Handle("/", next).Methods("GET") + srv := http.Server{ + Addr: ":9999", + Handler: app, + } + log.Fatal(srv.ListenAndServe()) +} diff --git a/example/main.go b/example/main.go index 68d2299..63ff95e 100644 --- a/example/main.go +++ b/example/main.go @@ -1,17 +1,35 @@ package main import ( - "git.echinacities.com/mogfee/protoc-gen-kit/example/service" - user "git.echinacities.com/mogfee/protoc-gen-kit/proto/v1" + "fmt" + "git.diulo.com/mogfee/protoc-gen-kit/example/service" + "git.diulo.com/mogfee/protoc-gen-kit/middleware" + user "git.diulo.com/mogfee/protoc-gen-kit/proto/v1" + "git.diulo.com/mogfee/protoc-gen-kit/xjson" "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" + "os" ) func main() { + gin.SetMode(gin.ReleaseMode) app := gin.Default() srv := service.UserService{} - app.Use(func(c *gin.Context) { - c.Set("userId", 11) + l := logrus.New() + f, err := os.Create("./app.log") + if err != nil { + panic(err) + } + defer f.Close() + l.SetOutput(f) + + l.SetFormatter(&logrus.JSONFormatter{}) + l.SetReportCaller(false) + + app.GET("/user/:name", func(c *gin.Context) { + xjson.PrintData(c.FullPath()) }) - user.RegisterUserHandler(app, &srv) + user.RegisterUserHandler(app, &srv, middleware.JWT(""), middleware.Logger("user-server", l), middleware.Validate()) + fmt.Println("http://localhost:8888") app.Run("localhost:8888") } diff --git a/example/service/service.go b/example/service/service.go index 5c965c2..8416d1a 100644 --- a/example/service/service.go +++ b/example/service/service.go @@ -3,9 +3,8 @@ package service import ( "context" "encoding/json" - "errors" - user "git.echinacities.com/mogfee/protoc-gen-kit/proto/v1" - "git.echinacities.com/mogfee/protoc-gen-kit/xerrors" + user "git.diulo.com/mogfee/protoc-gen-kit/proto/v1" + "git.diulo.com/mogfee/protoc-gen-kit/xerrors" ) type UserService struct { @@ -13,7 +12,6 @@ type UserService struct { } func (*UserService) Login(ctx context.Context, req *user.LoginRequest) (*user.LoginResponse, error) { - return nil, xerrors.BadRequest("BadRequest", "B") b, _ := json.Marshal(req) @@ -21,13 +19,13 @@ func (*UserService) Login(ctx context.Context, req *user.LoginRequest) (*user.Lo } func (*UserService) List(ctx context.Context, req *user.LoginRequest) (*user.LoginResponse, error) { //fmt.Println(ctx.Value("userId")) - //return nil, xerrors.InternalServer("InternalServer", "B") + //return nil, errors.Wrap(xerrors.InternalServer("InternalServer", "B"), "") //b, _ := json.Marshal(req) - return &user.LoginResponse{Token: ""}, nil + return &user.LoginResponse{Token: "123123"}, nil } func (*UserService) Delete(ctx context.Context, req *user.LoginRequest) (*user.LoginResponse, error) { - return nil, errors.New("bad err") + //return nil, errors.New("bad err") b, _ := json.Marshal(req) return &user.LoginResponse{Token: string(b)}, nil diff --git a/go.mod b/go.mod index 56fe507..b9acd20 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module git.echinacities.com/mogfee/protoc-gen-kit +module git.diulo.com/mogfee/protoc-gen-kit go 1.18 @@ -19,6 +19,7 @@ require ( github.com/go-playground/validator/v10 v10.10.0 // indirect github.com/goccy/go-json v0.9.7 // indirect github.com/golang/snappy v0.0.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-isatty v0.0.14 // indirect @@ -26,7 +27,9 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/nsqio/go-nsq v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.0.1 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/robfig/cron v1.2.0 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/ugorji/go/codec v1.2.7 // indirect golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect diff --git a/go.sum b/go.sum index a2dbbe3..b83f4d4 100644 --- a/go.sum +++ b/go.sum @@ -47,6 +47,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -70,6 +72,8 @@ github.com/nsqio/go-nsq v1.1.0/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQT github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -78,6 +82,8 @@ github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfm github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -111,6 +117,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/main.go b/main.go index 9609397..06712b7 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,7 @@ import ( "log" ) -//go build && protoc --unknow_out=./proto --go_out=./proto/ --go-grpc_out=./proto proto/user.proto -I ./proto +// 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{ @@ -28,7 +28,10 @@ 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("context") + u.addImports("git.diulo.com/mogfee/protoc-gen-kit/middleware") + u.addImports("git.diulo.com/mogfee/protoc-gen-kit/response") + u.addImports("git.diulo.com/mogfee/protoc-gen-kit/xerrors") u.addImports("github.com/gin-gonic/gin") for _, f := range plugin.Files { if len(f.Services) == 0 { @@ -45,13 +48,13 @@ func (u *Kit) Generate(plugin *protogen.Plugin) error { for _, s := range f.Services { serverName := s.GoName - t.P(`func Register`, serverName, `Handler(app *gin.Engine,srv `, serverName, `Server) {`) + t.P(`func Register`, serverName, `Handler(app *gin.Engine,srv `, serverName, `Server,m ...middleware.Middleware) {`) for _, m := range s.Methods { method, path := u.getMethod(m) if method == "" { continue } - t.P(`app.`, method, `("`, path, `",http`, m.GoName, `Handler(srv))`) + t.P(`app.`, method, `("`, path, `",http`, m.GoName, `Handler(srv,m...))`) } t.P(`}`) } @@ -78,72 +81,93 @@ func (u *Kit) Generate(plugin *protogen.Plugin) error { } func (u *Kit) genGet(serverName string, t *protogen.GeneratedFile, m *protogen.Method) { - t.P("func http", m.GoName, "Handler(srv ", serverName, "Server)func(c *gin.Context){") + t.P("func http", m.GoName, "Handler(srv ", serverName, "Server,m ...middleware.Middleware)func(c *gin.Context){") t.P(`return func(c *gin.Context) { - post := `, m.Input.GoIdent.GoName, `{} + var 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) + h := func(ctx context.Context, a any) (any, error) { + return srv.List(ctx, a.(*`, m.Input.GoIdent.GoName, `)) + } + out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) - return + } else { + if v, ok := out.(*`, m.Output.GoIdent.GoName, `); ok { + resp.Success(v) + } else { + resp.Error(xerrors.InternalServer("RESULT_TYPE_ERROR", "`, m.Output.GoIdent.GoName, `")) + } } - resp.Success(result) }`) t.P("}") } func (u *Kit) genPost(serverName string, t *protogen.GeneratedFile, m *protogen.Method) { - t.P("func http", m.GoName, "Handler(srv ", serverName, "Server)func(c *gin.Context){") + t.P("func http", m.GoName, "Handler(srv ", serverName, "Server,m ...middleware.Middleware)func(c *gin.Context){") t.P(`return func(c *gin.Context) { - post := `, m.Input.GoIdent.GoName, `{} + var 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) + h := func(ctx context.Context, a any) (any, error) { + return srv.List(ctx, a.(*`, m.Input.GoIdent.GoName, `)) + } + out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) - return + } else { + if v, ok := out.(*`, m.Output.GoIdent.GoName, `); ok { + resp.Success(v) + } else { + resp.Error(xerrors.InternalServer("RESULT_TYPE_ERROR", "`, m.Output.GoIdent.GoName, `")) + } } - resp.Success(result) }`) t.P("}") } func (u *Kit) genDelete(serverName string, t *protogen.GeneratedFile, m *protogen.Method) { - t.P("func http", m.GoName, "Handler(srv ", serverName, "Server)func(c *gin.Context){") + t.P("func http", m.GoName, "Handler(srv ", serverName, "Server,m ...middleware.Middleware)func(c *gin.Context){") t.P(`return func(c *gin.Context) { - post := `, m.Input.GoIdent.GoName, `{} + var 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) + h := func(ctx context.Context, a any) (any, error) { + return srv.List(ctx, a.(*`, m.Input.GoIdent.GoName, `)) + } + out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) - return + } else { + if v, ok := out.(*`, m.Output.GoIdent.GoName, `); ok { + resp.Success(v) + } else { + resp.Error(xerrors.InternalServer("RESULT_TYPE_ERROR", "`, m.Output.GoIdent.GoName, `")) + } } - resp.Success(result) }`) t.P("}") } -//func (Kit) getAuth(m *protogen.Method) *auth.AuthInfo { -// 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 +// func (Kit) getAuth(m *protogen.Method) *auth.AuthInfo { +// 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 +// } // } // } +// return &auth.AuthInfo{} // } -// return &auth.AuthInfo{} -//} 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 { diff --git a/middleware/add_header_md.go b/middleware/add_header_md.go new file mode 100644 index 0000000..a335505 --- /dev/null +++ b/middleware/add_header_md.go @@ -0,0 +1,26 @@ +package middleware + +import ( + "context" + "fmt" + "github.com/gin-gonic/gin" + "google.golang.org/grpc/metadata" +) + +func AddHeaderMdMiddle(c *gin.Context) Middleware { + return func(handler Handler) Handler { + return func(ctx context.Context, a any) (any, error) { + fmt.Println("add_header_md") + headers := metadata.MD{} + headers1 := c.Request.Header.Clone() + for k, v := range headers1 { + headers.Set(k, v[0]) + } + headers["remote_ip"] = []string{c.RemoteIP()} + headers["full_path"] = []string{c.FullPath()} + ctx = metadata.NewIncomingContext(ctx, headers) + + return handler(ctx, a) + } + } +} diff --git a/middleware/jwt.go b/middleware/jwt.go new file mode 100644 index 0000000..749f448 --- /dev/null +++ b/middleware/jwt.go @@ -0,0 +1,25 @@ +package middleware + +import ( + "context" + "git.diulo.com/mogfee/protoc-gen-kit/xuser" + "google.golang.org/grpc/metadata" +) + +func JWT(authKey string) Middleware { + return func(handler Handler) Handler { + return func(ctx context.Context, a any) (any, error) { + var token string + if md, ok := metadata.FromIncomingContext(ctx); ok { + token = md.Get("token")[0] + } + userId, err := xuser.ValidateUser(ctx.Value(token).(string)) + if err != nil { + return nil, err + } + + ctx = xuser.WithContext(ctx, userId) + return handler(ctx, a) + } + } +} diff --git a/middleware/logger.go b/middleware/logger.go new file mode 100644 index 0000000..86b113d --- /dev/null +++ b/middleware/logger.go @@ -0,0 +1,41 @@ +package middleware + +import ( + "context" + "fmt" + "git.diulo.com/mogfee/protoc-gen-kit/xlog" + "github.com/sirupsen/logrus" + "google.golang.org/grpc/metadata" + "time" +) + +func Logger(serverName string, log *logrus.Logger) Middleware { + baseEntry := log.WithFields(logrus.Fields{ + "serverName": serverName, + }) + return func(handler Handler) Handler { + return func(ctx context.Context, a any) (any, error) { + fmt.Println("add_log") + st := time.Now() + entry := baseEntry.WithFields(logrus.Fields{ + "used_time": time.Since(st), + "param": a, + }) + if md, ok := metadata.FromIncomingContext(ctx); ok { + entry = entry.WithFields(logrus.Fields{ + "ip": md.Get("remote_ip")[0], + "full_path": md.Get("full_path")[0], + }) + } + + ctx = xlog.WithContext(ctx, entry) + resp, err := handler(ctx, a) + if err != nil { + entry.WithContext(ctx).Errorf("%+v", err) + } else { + entry.WithContext(ctx).Info("") + } + return resp, err + } + } +} diff --git a/middleware/middleware.go b/middleware/middleware.go new file mode 100644 index 0000000..2888296 --- /dev/null +++ b/middleware/middleware.go @@ -0,0 +1,34 @@ +package middleware + +import ( + "context" + "fmt" + "github.com/gin-gonic/gin" +) + +type Handler func(context.Context, any) (any, error) + +type Middleware func(Handler) Handler + +func Chain(m ...Middleware) Middleware { + return func(handler Handler) Handler { + for i := len(m) - 1; i >= 0; i-- { + handler = m[i](handler) + } + return handler + } +} + +func HttpMiddleware(c *gin.Context, handler Handler, m ...Middleware) Handler { + opts := []Middleware{Recover(), AddHeaderMdMiddle(c), func(handler Handler) Handler { + return func(ctx context.Context, a any) (any, error) { + res, err := handler(ctx, a) + fmt.Println("sss", res) + return &struct { + Name string + }{}, err + } + }} + opts = append(opts, m...) + return Chain(opts...)(handler) +} diff --git a/middleware/recover.go b/middleware/recover.go new file mode 100644 index 0000000..f7779c8 --- /dev/null +++ b/middleware/recover.go @@ -0,0 +1,20 @@ +package middleware + +import ( + "context" + "fmt" +) + +func Recover() Middleware { + return func(handler Handler) Handler { + return func(ctx context.Context, a any) (res any, err error) { + go func() { + if rev := recover(); rev != nil { + err = fmt.Errorf("recover %v", rev) + } + }() + res, err = handler(ctx, a) + return + } + } +} diff --git a/middleware/validate.go b/middleware/validate.go new file mode 100644 index 0000000..192ee3c --- /dev/null +++ b/middleware/validate.go @@ -0,0 +1,23 @@ +package middleware + +import ( + "context" + "fmt" +) + +func Validate() Middleware { + return func(handler Handler) Handler { + return func(ctx context.Context, a any) (any, error) { + fmt.Println("validate") + fmt.Println(ctx.Value("user-id")) + if r, ok := a.(interface { + Validate() error + }); ok { + if err := r.Validate(); err != nil { + return nil, err + } + } + return handler(ctx, a) + } + } +} diff --git a/proto/auth/auth.proto b/proto/auth/auth.proto index d76b116..55109f8 100644 --- a/proto/auth/auth.proto +++ b/proto/auth/auth.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package auth; -option go_package = "git.echinacities.com/mogfee/protoc-gen-kit/proto/v1/auth;auth"; +option go_package = "git.diulo.com/mogfee/protoc-gen-kit/proto/v1/auth;auth"; import "google/protobuf/descriptor.proto"; diff --git a/proto/v1/user.gin.go b/proto/v1/user.gin.go index 50c069f..789c0da 100644 --- a/proto/v1/user.gin.go +++ b/proto/v1/user.gin.go @@ -1,43 +1,60 @@ package user import ( - "git.echinacities.com/mogfee/protoc-gen-kit/response" + "context" + "git.diulo.com/mogfee/protoc-gen-kit/middleware" + "git.diulo.com/mogfee/protoc-gen-kit/response" + "git.diulo.com/mogfee/protoc-gen-kit/xerrors" "github.com/gin-gonic/gin" ) -func RegisterUserHandler(app *gin.Engine, srv UserServer) { - app.GET("/api/v1/user/list", httpListHandler(srv)) - app.POST("/api/v1/user/login", httpLoginHandler(srv)) +func RegisterUserHandler(app *gin.Engine, srv UserServer, m ...middleware.Middleware) { + app.GET("/api/v1/user/list", httpListHandler(srv, m...)) + app.POST("/api/v1/user/login", httpLoginHandler(srv, m...)) } -func httpListHandler(srv UserServer) func(c *gin.Context) { +func httpListHandler(srv UserServer, m ...middleware.Middleware) func(c *gin.Context) { return func(c *gin.Context) { - post := LoginRequest{} + var post LoginRequest resp := response.New(c) if err := resp.BindQuery(&post); err != nil { resp.Error(err) return } - result, err := srv.List(c, &post) + h := func(ctx context.Context, a any) (any, error) { + return srv.List(ctx, a.(*LoginRequest)) + } + out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) - return + } else { + if v, ok := out.(*LoginResponse); ok { + resp.Success(v) + } else { + resp.Error(xerrors.InternalServer("RESULT_TYPE_ERROR", "LoginResponse")) + } } - resp.Success(result) } } -func httpLoginHandler(srv UserServer) func(c *gin.Context) { +func httpLoginHandler(srv UserServer, m ...middleware.Middleware) func(c *gin.Context) { return func(c *gin.Context) { - post := LoginRequest{} + var post LoginRequest resp := response.New(c) if err := resp.BindJSON(&post); err != nil { resp.Error(err) return } - result, err := srv.Login(c, &post) + h := func(ctx context.Context, a any) (any, error) { + return srv.List(ctx, a.(*LoginRequest)) + } + out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) - return + } else { + if v, ok := out.(*LoginResponse); ok { + resp.Success(v) + } else { + resp.Error(xerrors.InternalServer("RESULT_TYPE_ERROR", "LoginResponse")) + } } - resp.Success(result) } } diff --git a/response/response.go b/response/response.go index aff96e5..a5e4f86 100644 --- a/response/response.go +++ b/response/response.go @@ -2,16 +2,14 @@ package response import ( "encoding/json" - "git.echinacities.com/mogfee/protoc-gen-kit/xerrors" + "git.diulo.com/mogfee/protoc-gen-kit/xerrors" + "git.diulo.com/mogfee/protoc-gen-kit/xjson" + "git.diulo.com/mogfee/protoc-gen-kit/xstring" "github.com/gin-gonic/gin" "github.com/go-playground/form" "net/http" ) -var ( - code codec -) - type result struct { ctx *gin.Context } @@ -20,37 +18,12 @@ func New(ctx *gin.Context) *result { return &result{ctx: ctx} } -func (s *result) BindJSON(v any) error { - err := s.ShouldBindJson(v) - if err != nil { - return err - } - if r, ok := v.(interface { - Validate() error - }); ok { - return r.Validate() - } - return nil -} func (s *result) BindQuery(v any) error { - err := s.ShouldBindQuery(v) - if err != nil { - return err - } - if r, ok := v.(interface { - Validate() error - }); ok { - return r.Validate() - } - return nil -} - -func (s *result) ShouldBindQuery(v any) error { decoder := form.NewDecoder() decoder.SetTagName("json") return decoder.Decode(v, s.ctx.Request.URL.Query()) } -func (s *result) ShouldBindJson(v any) error { +func (s *result) BindJSON(v any) error { body := s.ctx.Request.Body decoder := json.NewDecoder(body) return decoder.Decode(v) @@ -62,7 +35,7 @@ func (s *result) Error(err error) { //参数错误 if vv, ok := err.(ValidateError); ok { s.Result(http.StatusBadRequest, "InvalidArgument", vv.ErrorName(), map[string]string{ - vv.Field(): vv.Reason(), + xstring.Lcfirst(vv.Field()): vv.Reason(), }) return } @@ -81,7 +54,7 @@ type MyRender struct { } func (m *MyRender) Render(writer http.ResponseWriter) error { - jsonBytes, err := code.Marshal(m.Data) + jsonBytes, err := xjson.Marshal(m.Data) if err != nil { return err } @@ -107,3 +80,10 @@ func (s *result) Result(httpCode int, reason string, message string, metadata ma "metadata": metadata, }) } +func (s *result) ServerResult(res any, err error) { + if err != nil { + s.Error(err) + } else { + s.Success(res) + } +} diff --git a/response/json.go b/xjson/xjson.go similarity index 84% rename from response/json.go rename to xjson/xjson.go index 561de14..0ae55e2 100644 --- a/response/json.go +++ b/xjson/xjson.go @@ -1,7 +1,8 @@ -package response +package xjson import ( "encoding/json" + "fmt" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "reflect" @@ -18,10 +19,7 @@ var ( } ) -type codec struct { -} - -func (codec) Marshal(v interface{}) ([]byte, error) { +func Marshal(v interface{}) ([]byte, error) { switch m := v.(type) { case json.Marshaler: return m.MarshalJSON() @@ -32,7 +30,7 @@ func (codec) Marshal(v interface{}) ([]byte, error) { } } -func (codec) Unmarshal(data []byte, v interface{}) error { +func Unmarshal(data []byte, v interface{}) error { switch m := v.(type) { case json.Unmarshaler: return m.UnmarshalJSON(data) @@ -52,3 +50,8 @@ func (codec) Unmarshal(data []byte, v interface{}) error { return json.Unmarshal(data, m) } } + +func PrintData(a any) { + b, _ := Marshal(a) + fmt.Println(string(b)) +} diff --git a/xlog/xlog.go b/xlog/xlog.go new file mode 100644 index 0000000..052a296 --- /dev/null +++ b/xlog/xlog.go @@ -0,0 +1,19 @@ +package xlog + +import ( + "context" + "github.com/sirupsen/logrus" +) + +type entryKey struct { +} + +func WithContext(ctx context.Context, entry *logrus.Entry) context.Context { + return context.WithValue(ctx, entryKey{}, entry) +} +func FromContext(ctx context.Context) *logrus.Entry { + if v, ok := ctx.Value(entryKey{}).(*logrus.Entry); ok { + return v + } + return &logrus.Entry{} +} diff --git a/xstring/xstring.go b/xstring/xstring.go new file mode 100644 index 0000000..0b89969 --- /dev/null +++ b/xstring/xstring.go @@ -0,0 +1,17 @@ +package xstring + +import "unicode" + +func Ucfirst(str string) string { + for i, v := range str { + return string(unicode.ToUpper(v)) + str[i+1:] + } + return "" +} + +func Lcfirst(str string) string { + for i, v := range str { + return string(unicode.ToLower(v)) + str[i+1:] + } + return "" +} diff --git a/xuser/xuser.go b/xuser/xuser.go new file mode 100644 index 0000000..6a0dc14 --- /dev/null +++ b/xuser/xuser.go @@ -0,0 +1,20 @@ +package xuser + +import "context" + +func ValidateUser(token string) (int64, error) { + return 1, nil +} + +type userIdKey struct { +} + +func WithContext(ctx context.Context, userId int64) context.Context { + return context.WithValue(ctx, userIdKey{}, userId) +} +func FromContext(ctx context.Context) int64 { + if v, ok := ctx.Value(userIdKey{}).(int64); ok { + return v + } + return 0 +}