github.com/lenfree/buffalo@v0.7.3-0.20170207163156-891616ea4064/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  }
    52  
    53  func init() {
    54  	jb := func(req *http.Request, value interface{}) error {
    55  		return json.NewDecoder(req.Body).Decode(value)
    56  	}
    57  	binders["application/json"] = jb
    58  	binders["text/json"] = jb
    59  	binders["json"] = jb
    60  }
    61  
    62  func init() {
    63  	xb := func(req *http.Request, value interface{}) error {
    64  		return xml.NewDecoder(req.Body).Decode(value)
    65  	}
    66  	binders["application/xml"] = xb
    67  	binders["text/xml"] = xb
    68  	binders["xml"] = xb
    69  }