master
parent
b731d13a88
commit
25c38491fe
20 changed files with 448 additions and 95 deletions
@ -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()) |
||||
} |
@ -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") |
||||
} |
||||
|
@ -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) |
||||
} |
||||
} |
||||
} |
@ -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) |
||||
} |
||||
} |
||||
} |
@ -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 |
||||
} |
||||
} |
||||
} |
@ -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) |
||||
} |
@ -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 |
||||
} |
||||
} |
||||
} |
@ -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) |
||||
} |
||||
} |
||||
} |
@ -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) |
||||
} |
||||
} |
||||
|
@ -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{} |
||||
} |
@ -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 "" |
||||
} |
@ -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 |
||||
} |
Loading…
Reference in new issue