github.com/jasonish/buffalo@v0.8.2-0.20170413145823-bacbdd415f1b/binding.go (about) 1 package buffalo 2 3 import ( 4 "encoding/json" 5 "encoding/xml" 6 "net/http" 7 "reflect" 8 "sync" 9 10 "github.com/gorilla/schema" 11 "github.com/markbates/pop/nulls" 12 "github.com/pkg/errors" 13 ) 14 15 var binderLock = &sync.Mutex{} 16 var binders = map[string]BinderFunc{} 17 var schemaDecoder *schema.Decoder 18 19 // BinderFunc takes a request and binds it to an interface. 20 // If there is a problem it should return an error. 21 type BinderFunc func(*http.Request, interface{}) error 22 23 // RegisterBinder maps a request Content-Type (application/json) 24 // to a BinderFunc. 25 func RegisterBinder(contentType string, fn BinderFunc) { 26 binderLock.Lock() 27 defer binderLock.Unlock() 28 binders[contentType] = fn 29 } 30 31 func init() { 32 schemaDecoder = schema.NewDecoder() 33 schemaDecoder.IgnoreUnknownKeys(true) 34 schemaDecoder.ZeroEmpty(true) 35 36 // register the types in the nulls package with the decoder 37 nulls.RegisterWithSchema(func(i interface{}, fn func(s string) reflect.Value) { 38 schemaDecoder.RegisterConverter(i, fn) 39 }) 40 41 sb := func(req *http.Request, value interface{}) error { 42 err := req.ParseForm() 43 if err != nil { 44 return errors.WithStack(err) 45 } 46 return schemaDecoder.Decode(value, req.PostForm) 47 } 48 binders["application/html"] = sb 49 binders["text/html"] = sb 50 binders["application/x-www-form-urlencoded"] = sb 51 binders["multipart/form-data"] = sb 52 } 53 54 func init() { 55 jb := func(req *http.Request, value interface{}) error { 56 return json.NewDecoder(req.Body).Decode(value) 57 } 58 binders["application/json"] = jb 59 binders["text/json"] = jb 60 binders["json"] = jb 61 } 62 63 func init() { 64 xb := func(req *http.Request, value interface{}) error { 65 return xml.NewDecoder(req.Body).Decode(value) 66 } 67 binders["application/xml"] = xb 68 binders["text/xml"] = xb 69 binders["xml"] = xb 70 }