diff --git a/example/bind/main.go b/example/bind/main.go index 4cd0626..438f6c4 100644 --- a/example/bind/main.go +++ b/example/bind/main.go @@ -1,10 +1,15 @@ package main import ( + "encoding/json" + "encoding/xml" + "errors" "fmt" "github.com/devfeel/dotweb" "github.com/devfeel/dotweb/framework/file" + "github.com/devfeel/dotweb/framework/reflects" "strconv" + "strings" ) func main() { @@ -22,6 +27,9 @@ func main() { //设置gzip开关 //app.HttpServer.SetEnabledGzip(true) + //设置自定义绑定器 + app.HttpServer.SetBinder(newUserBinder()) + //设置路由 InitRoute(app.HttpServer) @@ -92,3 +100,53 @@ func InitRoute(server *dotweb.HttpServer) { server.Router().GET("/getbind", GetBind) server.Router().POST("/jsonbind", PostJsonBind) } + + +type userBinder struct{ + +} + +//Bind decode req.Body or form-value to struct +func (b *userBinder) Bind(i interface{}, ctx dotweb.Context) (err error) { + fmt.Println("UserBind.Bind") + req := ctx.Request() + ctype := req.Header.Get(dotweb.HeaderContentType) + if req.Body == nil { + err = errors.New("request body can't be empty") + return err + } + err = errors.New("request unsupported MediaType -> " + ctype) + switch { + case strings.HasPrefix(ctype, dotweb.MIMEApplicationJSON): + err = json.Unmarshal(ctx.Request().PostBody(), i) + case strings.HasPrefix(ctype, dotweb.MIMEApplicationXML): + err = xml.Unmarshal(ctx.Request().PostBody(), i) + //case strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm), + // strings.HasPrefix(ctype, MIMETextHTML): + // err = reflects.ConvertMapToStruct(defaultTagName, i, ctx.FormValues()) + default: + //check is use json tag, fixed for issue #91 + tagName := "form" + if ctx.HttpServer().ServerConfig().EnabledBindUseJsonTag{ + tagName = "json" + } + //no check content type for fixed issue #6 + err = reflects.ConvertMapToStruct(tagName, i, ctx.Request().FormValues()) + } + return err +} + +//BindJsonBody default use json decode req.Body to struct +func (b *userBinder) BindJsonBody(i interface{}, ctx dotweb.Context) (err error) { + fmt.Println("UserBind.BindJsonBody") + if ctx.Request().PostBody() == nil { + err = errors.New("request body can't be empty") + return err + } + err = json.Unmarshal(ctx.Request().PostBody(), i) + return err +} + +func newUserBinder() *userBinder { + return &userBinder{} +} diff --git a/server.go b/server.go index 4d723c6..bec2aea 100644 --- a/server.go +++ b/server.go @@ -102,6 +102,11 @@ func (server *HttpServer) SessionConfig() *config.SessionNode { return server.DotApp.Config.Session } +// SetBinder set custom Binder on HttpServer +func (server *HttpServer) SetBinder(binder Binder){ + server.binder = binder +} + // ListenAndServe listens on the TCP network address srv.Addr and then // calls Serve to handle requests on incoming connections. func (server *HttpServer) ListenAndServe(addr string) error { diff --git a/version.MD b/version.MD index b9f0421..61815ad 100644 --- a/version.MD +++ b/version.MD @@ -1,5 +1,16 @@ ## dotweb版本记录: +#### Version 1.5.8 +* New Feature: Add HttpServer.SetBinder, used to set custom Binder on HttpServer +* Detail: + - Custom binder must implement dotweb.Binder interface +* Example: + ``` golang + app.HttpServer.SetBinder(newUserBinder()) + ``` +* update example/bind +* 2018-10-24 21:00 + #### Version 1.5.7.8 * Improve Comments about session Maxlifetime * Session.StoreConfig.Maxlifetime: session life time, with second