package api import ( "fmt" "reflect" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "qoobing.com/gomod/log" "qoobing.com/gomod/str" ) var ( validate = validator.New() requestLogidGetter = defaultLogidGetter handlerMapper = map[string]Handler{} errCodeUnknownError = -10000 errCodeParameterError = -20000 errCodeUnimplementApi = -20401 ) type Engine struct { *gin.Engine } type BaseWithEnoOutput struct { Eno int `json:"eno"` Err string `json:"err"` } type BaseWithCodeOutput struct { Code int `json:"code"` Msg string `json:"msg"` } type BaseWithErrCodeOutput struct { ErrCode int `json:"errCode"` ErrMsg string `json:"errMsg"` } func NewEngine() *Engine { gin.SetMode(gin.ReleaseMode) e := gin.New() e.Use(middlewareMyApiEngine()) return &Engine{e} } func (e *Engine) POST(uri string, handler Handler) { h := handlerWrapper(handler.HandlerFunc()) handlerMapper[fmt.Sprintf("%v", h)] = handler e.Engine.POST(uri, h) } // handlerWrapper func handlerWrapper(handler HandlerFunc) gin.HandlerFunc { return func(c *gin.Context) { if icc, ok := c.Get("cc"); !ok { log.Errorf("Unreachable Code: can not get cc(*api.Context) from *gin.Context") } else if cc, ok := icc.(*Context); !ok { log.Debugf("Unreachable Code: cc from *gin.Context is type of:[%s]", reflect.TypeOf(icc).String()) log.Errorf("Unreachable Code: cc from *gin.Context is not type of *api.Context") } else { defer cc.TryRecover() cc.AppId = c.GetString("appid") cc.UserId = c.GetUint64("userid") handler(cc) } } } // middlewareMyApiEngine myapi engine middleware func middlewareMyApiEngine() gin.HandlerFunc { return func(c *gin.Context) { // Step 1. set logid id := requestLogidGetter(c) log.SetLogid(id) defer log.Cleanup() // Step 2. init *api.Context cc := New(c) c.Set("cc", cc) // Step 3. do request c.Next() } } // defaultLogidGetter get logid from "X-Request-Id" or create a new one. func defaultLogidGetter(c *gin.Context) (logid string) { if logid = c.Request.Header.Get("X-Request-Id"); logid != "" { return logid } if logid = str.GetRandomNumString(13); logid != "" { return logid } panic("unreachable code") } func DumpHandler(c *Context) error { errmsg := "api not implemented" errcode := errCodeUnimplementApi return c.RESULT_ERROR(errcode, errmsg) } func ErrorHandler(c *gin.Context, errcode int, errmsg string) { handler := handlerWrapper(func(c *Context) error { return c.RESULT_ERROR(errcode, errmsg) }) handler(c) } func InitErrCodes(errcodes map[string]int) { if code, ok := errcodes["ErrCodeUnknownError"]; ok { errCodeUnknownError = code } if code, ok := errcodes["ErrCodeUnimplementApi"]; ok { errCodeUnknownError = code } if code, ok := errcodes["errCodeParameterError"]; ok { errCodeParameterError = code } }