119 lines
2.7 KiB
Go
119 lines
2.7 KiB
Go
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
|
|
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
|
|
}
|
|
}
|