diff --git a/app/zeus/api/lark/internal/user/user.go b/app/zeus/api/lark/internal/user/user.go index e6f3d02..954d153 100644 --- a/app/zeus/api/lark/internal/user/user.go +++ b/app/zeus/api/lark/internal/user/user.go @@ -3,6 +3,7 @@ package user import ( "git.icechen.cn/monorepo/backend/pkg/proto/zeus/lark" "git.icechen.cn/monorepo/backend/pkg/rpc" + "git.icechen.cn/monorepo/backend/pkg/validator" "github.com/gofiber/fiber/v2" ctxLogger "github.com/luizsuper/ctxLoggers" "go.uber.org/zap" @@ -13,7 +14,7 @@ func LoginHandle(c *fiber.Ctx) error { Code string `json:"code" validate:"required"` Email string `json:"email" label:"邮箱" validate:"email"` }{} - err := Bind(c, &p) + err := validator.Bind(c, &p) if err != nil { return err } diff --git a/app/zeus/api/lark/main.go b/app/zeus/api/lark/main.go index 0d0f8a0..562703a 100755 --- a/app/zeus/api/lark/main.go +++ b/app/zeus/api/lark/main.go @@ -1,7 +1,7 @@ package main import ( - "encoding/json" + "git.icechen.cn/monorepo/backend/pkg/third_party" "git.icechen.cn/monorepo/backend/app/zeus/api/lark/internal/user" "github.com/gofiber/fiber/v2" @@ -11,9 +11,9 @@ import ( func main() { router := fiber.New(fiber.Config{ AppName: "api-lark", - ErrorHandler: middlewareError, + ErrorHandler: third_party.FiberErrHandler, }) - // router.Use(middlewareResp) + router.Use(third_party.FibberRespHandler) userRouter := router.Group("/user") userRouter.Post("/login", user.LoginHandle) @@ -23,42 +23,3 @@ func main() { ctxLogger.Error(nil, err.Error()) } } - -func middlewareResp(c *fiber.Ctx) error { - err := c.Next() - if err != nil { - return err - } - - resp := Response{ - Code: 0, - Message: "", - Data: c.Response().Body(), - } - return c.JSON(resp) -} - -type Response struct { - Code int `json:"code"` - Message string `json:"message"` - Data json.RawMessage `json:"data,omitempty"` -} - -func middlewareError(ctx *fiber.Ctx, err error) error { - code := fiber.StatusInternalServerError - msg := "" - - if e, ok := err.(*fiber.Error); ok { - code = e.Code - msg = e.Message - } - if err != nil { - msg = err.Error() - } - - return ctx.Status(code).JSON(Response{ - Code: code, - Message: msg, - Data: nil, - }) -} diff --git a/pkg/net/api_response.go b/pkg/net/api_response.go new file mode 100644 index 0000000..b53a7f2 --- /dev/null +++ b/pkg/net/api_response.go @@ -0,0 +1,11 @@ +// Package net 网络有关的库 +package net + +import "encoding/json" + +// Response 所有api统一返回格式 +type Response struct { + Code int `json:"code"` + Message string `json:"message"` + Data json.RawMessage `json:"data,omitempty"` +} diff --git a/pkg/third_party/fiber.go b/pkg/third_party/fiber.go new file mode 100644 index 0000000..8bc78da --- /dev/null +++ b/pkg/third_party/fiber.go @@ -0,0 +1,65 @@ +// Package third_party 关于所有第三方框架的二次封装 +package third_party + +import ( + "git.icechen.cn/monorepo/backend/pkg/net" + "github.com/gofiber/fiber/v2" +) + +// FiberErrHandler fiber 错误处理的中间件 +func FiberErrHandler(ctx *fiber.Ctx, err error) error { + code := fiber.StatusInternalServerError + msg := "" + + if e, ok := err.(*fiber.Error); ok { + code = e.Code + msg = e.Message + } + if err != nil { + msg = err.Error() + } + + return ctx.Status(code).JSON(net.Response{ + Code: code, + Message: msg, + Data: nil, + }) +} + +// FibberRespHandler fiber resp的统一处理 +func FibberRespHandler(c *fiber.Ctx) error { + if respContentType := string(c.Response().Header.ContentType()); respContentType == fiber.MIMEApplicationJSON { + resp := net.Response{ + Code: 0, + Message: "", + Data: c.Response().Body(), + } + return c.JSON(resp) + } + + return c.Next() +} + +//5 funcs for err 2 fiberErr + +func NewFError(msg string) error { + return fiber.NewError(fiber.StatusInternalServerError, msg) +} + +func NewFErrorWithCode(code int, msg string) error { + return fiber.NewError(code, msg) +} + +func WarpFError(err error) error { + if err == nil { + return nil + } + return fiber.NewError(fiber.StatusInternalServerError, err.Error()) +} + +func WarpFErrorWithCode(code int, err error) error { + if err == nil { + return nil + } + return fiber.NewError(code, err.Error()) +} diff --git a/pkg/validator/param_validator.go b/pkg/validator/param_validator.go new file mode 100644 index 0000000..83dfa7e --- /dev/null +++ b/pkg/validator/param_validator.go @@ -0,0 +1,68 @@ +// Package validator 校验器集合包 +package validator + +import ( + "fmt" + "git.icechen.cn/monorepo/backend/pkg/third_party" + "github.com/go-playground/locales/zh_Hans_CN" + ut "github.com/go-playground/universal-translator" + "github.com/go-playground/validator/v10" + zh_translations "github.com/go-playground/validator/v10/translations/zh" + "github.com/gofiber/fiber/v2" + "reflect" + "strings" +) + +var Validate *validator.Validate +var trans ut.Translator + +func init() { + Validate = validator.New() + zh := zh_Hans_CN.New() + uni := ut.New(zh, zh) + var ok bool + trans, ok = uni.GetTranslator("zh_Hans_CN") + if !ok { + panic(fmt.Errorf("uni.GetTranslator(%s) failed", "zh")) + } + Validate.RegisterTagNameFunc(func(field reflect.StructField) string { + addWarp := func(tag string) string { + return "[" + tag + "]" + } + if labelTag := field.Tag.Get("label"); labelTag != "" { + return addWarp(labelTag) + } + if jsonTag := field.Tag.Get("json"); jsonTag != "" { + return addWarp(jsonTag) + } + return addWarp(field.Name) + }) + err := zh_translations.RegisterDefaultTranslations(Validate, trans) + if err != nil { + panic(err) + } +} + +func Bind(c *fiber.Ctx, out interface{}) error { + if reflect.TypeOf(out).Kind() != reflect.Ptr { + return third_party.NewFError("bind must ptr") + } + + if err := c.BodyParser(out); err != nil { + return third_party.WarpFError(err) + } + + err := Validate.Struct(out) + + if err != nil { + if errs, ok := err.(validator.ValidationErrors); ok { + errString := make([]string, 0, len(errs)) + for _, fieldError := range errs.Translate(trans) { + errString = append(errString, fieldError) + } + err = fmt.Errorf("%s", strings.Join(errString, ",")) + } + return third_party.WarpFErrorWithCode(fiber.StatusBadRequest, err) + } + return nil +}