add bindoutput & rewrite shapeoutput
This commit is contained in:
parent
8489fc1556
commit
f978fa3f87
40
api.go
40
api.go
@ -1,6 +1,9 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"qoobing.com/gomod/log"
|
"qoobing.com/gomod/log"
|
||||||
@ -10,6 +13,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
validate = validator.New()
|
validate = validator.New()
|
||||||
requestLogidGetter = defaultLogidGetter
|
requestLogidGetter = defaultLogidGetter
|
||||||
|
handlerMapper = map[string]Handler{}
|
||||||
errCodeUnknownError = -10000
|
errCodeUnknownError = -10000
|
||||||
errCodeUnimplementApi = -20401
|
errCodeUnimplementApi = -20401
|
||||||
)
|
)
|
||||||
@ -40,8 +44,27 @@ func NewEngine() *Engine {
|
|||||||
return &Engine{e}
|
return &Engine{e}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) POST(uri string, handler HandlerFunc) {
|
func (e *Engine) POST(uri string, handler Handler) {
|
||||||
e.Engine.POST(uri, handlerWrapper(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
|
// middlewareMyApiEngine myapi engine middleware
|
||||||
@ -72,6 +95,19 @@ func defaultLogidGetter(c *gin.Context) (logid string) {
|
|||||||
panic("unreachable code")
|
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) {
|
func InitErrCodes(errcodes map[string]int) {
|
||||||
if code, ok := errcodes["ErrCodeUnknownError"]; ok {
|
if code, ok := errcodes["ErrCodeUnknownError"]; ok {
|
||||||
errCodeUnknownError = code
|
errCodeUnknownError = code
|
||||||
|
51
context.go
51
context.go
@ -25,6 +25,7 @@ type Context struct {
|
|||||||
resultentry string
|
resultentry string
|
||||||
httpstatus int
|
httpstatus int
|
||||||
starttime time.Time
|
starttime time.Time
|
||||||
|
output interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(c *gin.Context) *Context {
|
func New(c *gin.Context) *Context {
|
||||||
@ -89,6 +90,29 @@ func (c *Context) BindInput(i interface{}) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Context) BindOutput(o interface{}) (err error) {
|
||||||
|
var v = reflect.ValueOf(o)
|
||||||
|
if v.Kind() != reflect.Pointer {
|
||||||
|
return fmt.Errorf("output is NOT a pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
var e = v.Elem()
|
||||||
|
var t = e.Type()
|
||||||
|
if _, ok := t.FieldByName("ErrCode"); !ok {
|
||||||
|
return fmt.Errorf("out have no field ErrCode")
|
||||||
|
}
|
||||||
|
if _, ok := t.FieldByName("ErrMsg"); !ok {
|
||||||
|
return fmt.Errorf("out have no field ErrMsg")
|
||||||
|
}
|
||||||
|
if code := e.FieldByName("ErrCode"); !code.CanSet() {
|
||||||
|
return fmt.Errorf("output.ErrCode can not be set, " +
|
||||||
|
"output is NOT a pointer or output have no field 'ErrCode'")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.output = o
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Context) SetCookie(cookie *http.Cookie) {
|
func (c *Context) SetCookie(cookie *http.Cookie) {
|
||||||
if cookie.Path == "" {
|
if cookie.Path == "" {
|
||||||
cookie.Path = "/"
|
cookie.Path = "/"
|
||||||
@ -130,19 +154,46 @@ func (c *Context) RESULT(output interface{}) error {
|
|||||||
if _, ok := t.FieldByName("ErrCode"); !ok {
|
if _, ok := t.FieldByName("ErrCode"); !ok {
|
||||||
errstr := "Result MUST have 'ErrCode' field"
|
errstr := "Result MUST have 'ErrCode' field"
|
||||||
output = BaseWithErrCodeOutput{errCodeUnknownError, errstr}
|
output = BaseWithErrCodeOutput{errCodeUnknownError, errstr}
|
||||||
|
c.ShapeOutput(output)
|
||||||
c.IndentedJSON(c.httpstatus, output)
|
c.IndentedJSON(c.httpstatus, output)
|
||||||
return errors.New(errstr)
|
return errors.New(errstr)
|
||||||
}
|
}
|
||||||
if _, ok := t.FieldByName("ErrMsg"); !ok {
|
if _, ok := t.FieldByName("ErrMsg"); !ok {
|
||||||
errstr := "Result MUST have 'ErrMsg' field"
|
errstr := "Result MUST have 'ErrMsg' field"
|
||||||
output = BaseWithErrCodeOutput{errCodeUnknownError, errstr}
|
output = BaseWithErrCodeOutput{errCodeUnknownError, errstr}
|
||||||
|
c.ShapeOutput(output)
|
||||||
c.IndentedJSON(c.httpstatus, output)
|
c.IndentedJSON(c.httpstatus, output)
|
||||||
return errors.New(errstr)
|
return errors.New(errstr)
|
||||||
}
|
}
|
||||||
|
c.ShapeOutput(output)
|
||||||
c.IndentedJSON(c.httpstatus, output)
|
c.IndentedJSON(c.httpstatus, output)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Context) ShapeOutput(o interface{}) {
|
||||||
|
if c.output == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var out, ok = o.(BaseWithErrCodeOutput)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var e = reflect.ValueOf(c.output).Elem()
|
||||||
|
e.FieldByName("ErrMsg").SetString(out.ErrMsg)
|
||||||
|
e.FieldByName("ErrCode").SetInt(int64(out.ErrCode))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) Handler() Handler {
|
||||||
|
h := c.Context.Handler()
|
||||||
|
if handler, ok := handlerMapper[fmt.Sprintf("%v", h)]; ok {
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Context) RESULT_ERROR(eno int, err string) error {
|
func (c *Context) RESULT_ERROR(eno int, err string) error {
|
||||||
if c.resultentry == "" {
|
if c.resultentry == "" {
|
||||||
c.resultentry = "RESULT_ERROR"
|
c.resultentry = "RESULT_ERROR"
|
||||||
|
2
go.mod
2
go.mod
@ -1,6 +1,6 @@
|
|||||||
module qoobing.com/gomod/api
|
module qoobing.com/gomod/api
|
||||||
|
|
||||||
go 1.16
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-gonic/gin v1.8.1
|
github.com/gin-gonic/gin v1.8.1
|
||||||
|
76
routes.go
76
routes.go
@ -1,49 +1,43 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
// ///////////////////////////////////////////////////////////////////
|
||||||
"reflect"
|
// IRouter & IRoutes in gin, we redefine it simple
|
||||||
|
// ///////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// // IRouter defines all router handle interface
|
||||||
|
// // includes single and group router.
|
||||||
|
// type IRouter interface {
|
||||||
|
// IRoutes
|
||||||
|
// Group(string, ...HandlerFunc) *RouterGroup
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // IRoutes defines all router handle interface.
|
||||||
|
// type IRoutes interface {
|
||||||
|
// Use(...HandlerFunc) IRoutes
|
||||||
|
//
|
||||||
|
// Handle(string, string, ...HandlerFunc) IRoutes
|
||||||
|
// Any(string, ...HandlerFunc) IRoutes
|
||||||
|
// GET(string, ...HandlerFunc) IRoutes
|
||||||
|
// POST(string, ...HandlerFunc) IRoutes
|
||||||
|
// DELETE(string, ...HandlerFunc) IRoutes
|
||||||
|
// PATCH(string, ...HandlerFunc) IRoutes
|
||||||
|
// PUT(string, ...HandlerFunc) IRoutes
|
||||||
|
// OPTIONS(string, ...HandlerFunc) IRoutes
|
||||||
|
// HEAD(string, ...HandlerFunc) IRoutes
|
||||||
|
//
|
||||||
|
// StaticFile(string, string) IRoutes
|
||||||
|
// StaticFileFS(string, string, http.FileSystem) IRoutes
|
||||||
|
// Static(string, string) IRoutes
|
||||||
|
// StaticFS(string, http.FileSystem) IRoutes
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
type Handler interface {
|
||||||
"qoobing.com/gomod/log"
|
HandlerFunc() HandlerFunc
|
||||||
)
|
|
||||||
|
|
||||||
type routes struct {
|
|
||||||
gin.IRoutes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandlerFunc func(*Context) error
|
type HandlerFunc func(*Context) error
|
||||||
|
|
||||||
type IRoutes interface {
|
type IRoutes interface {
|
||||||
POST(uri string, handler HandlerFunc)
|
POST(uri string, handler Handler)
|
||||||
}
|
|
||||||
|
|
||||||
func (r routes) POST(uri string, handler HandlerFunc) {
|
|
||||||
r.IRoutes.POST(uri, handlerWrapper(handler))
|
|
||||||
}
|
|
||||||
|
|
||||||
func DumpHandler(c *Context) error {
|
|
||||||
return c.RESULT_ERROR(errCodeUnimplementApi, "api not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func ErrorHandler(c *gin.Context, errcode int, errmsg string) {
|
|
||||||
handler := handlerWrapper(func(c *Context) error {
|
|
||||||
return c.RESULT_ERROR(errcode, errmsg)
|
|
||||||
})
|
|
||||||
handler(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user