Documentation ¶
Overview ¶
Package binding deserializes data from HTTP requests into a struct ready for your application to use (without reflection). It also facilitates data validation and error handling.
Example (FieldBinder) ¶
package main import ( "fmt" "io" "log" "net/http" "net/http/httptest" "net/url" "os" "strconv" "github.com/mholt/binding" ) type MyType struct { SomeNumber int } func (t *MyType) FieldMap(req *http.Request) binding.FieldMap { return binding.FieldMap{ "a-key": binding.Field{ Form: "number", Binder: func(fieldName string, formVals []string) error { val, err := strconv.Atoi(formVals[0]) if err != nil { return binding.Errors{binding.NewError([]string{fieldName}, binding.DeserializationError, err.Error())} } t.SomeNumber = val return nil }, }, } } func main() { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { b := new(MyType) if err := binding.Bind(req, b); err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } fmt.Fprintf(w, "%d", b.SomeNumber) })) defer ts.Close() resp, err := http.DefaultClient.PostForm(ts.URL, url.Values{"number": []string{"1008"}}) if err != nil { log.Println(err) return } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) }
Output: 1008
Index ¶
- Constants
- Variables
- func Bind(req *http.Request, userStruct FieldMapper) error
- func Form(req *http.Request, userStruct FieldMapper) error
- func Json(req *http.Request, userStruct FieldMapper) error
- func MultipartForm(req *http.Request, userStruct FieldMapper) error
- func URL(req *http.Request, userStruct FieldMapper) error
- func Validate(req *http.Request, userStruct FieldMapper) error
- type Binder
- type Error
- type Errors
- type Field
- type FieldMap
- type FieldMapper
- type Validator
Examples ¶
Constants ¶
const ( RequiredError = "RequiredError" ContentTypeError = "ContentTypeError" DeserializationError = "DeserializationError" TypeError = "TypeError" )
const (
StatusUnprocessableEntity = 422
)
Variables ¶
var ( // Maximum amount of memory to use when parsing a multipart form. // Set this to whatever value you prefer; default is 10 MB. MaxMemory = int64(1024 * 1024 * 10) // If no TimeFormat is specified for a time.Time field, this // format will be used by default when parsing. TimeFormat = time.RFC3339 )
Functions ¶
func Bind ¶
func Bind(req *http.Request, userStruct FieldMapper) error
Bind takes data out of the request and deserializes into a struct according to the Content-Type of the request. If no Content-Type is specified, there better be data in the query string, otherwise an error will be produced.
A non-nil return value may be an Errors value.
func Form ¶
func Form(req *http.Request, userStruct FieldMapper) error
Form deserializes form data out of the request into a struct you provide. This function invokes data validation after deserialization.
func Json ¶
func Json(req *http.Request, userStruct FieldMapper) error
Json deserializes a JSON request body into a struct you specify using the standard encoding/json package (which uses reflection). This function invokes data validation after deserialization.
func MultipartForm ¶
func MultipartForm(req *http.Request, userStruct FieldMapper) error
MultipartForm reads a multipart form request and deserializes its data and files into a struct you provide. Files should be deserialized into *multipart.FileHeader fields.
Types ¶
type Binder ¶
type Binder interface { // Bind populates the type with data in []string which comes from the // HTTP request. The first argument is the field name. Bind(string, []string) error }
Binder is an interface which can deserialize itself from a slice of string coming from the request. Implement this interface so the type can be populated from form data in HTTP requests.
Example ¶
package main import ( "fmt" "io" "log" "net/http" "net/http/httptest" "net/url" "os" "github.com/mholt/binding" ) type MyBinder map[string]string func (t MyBinder) Bind(fieldName string, strVals []string) error { t["formData"] = strVals[0] return nil } type MyBinderContainer struct { Important MyBinder } func (c *MyBinderContainer) FieldMap(req *http.Request) binding.FieldMap { return binding.FieldMap{ &c.Important: "important", } } func main() { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { v := new(MyBinderContainer) v.Important = make(MyBinder) if err := binding.Bind(req, v); err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } fmt.Fprintf(w, v.Important["formData"]) })) defer ts.Close() resp, err := http.DefaultClient.PostForm(ts.URL, url.Values{"important": []string{"1008"}}) if err != nil { log.Println(err) return } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) }
Output: 1008
type Error ¶
An Error is an error that is associated with 0 or more fields of a request.
Fields should return the fields associated with the error. When the return value's length is 0, something is wrong with the request as a whole.
Kind should return a string that can be used like an error code to process or categorize the Error.
Message should return the error message.
type Errors ¶
type Errors []Error
Errors may be generated during deserialization, binding, or validation.
func (*Errors) Add ¶
Add adds an Error associated with the fields indicated by fieldNames, with the given kind and message.
Use a fieldNames value of length 0 to indicate that the error is about the request as a whole, and not necessarily any of the fields.
kind should be a string that can be used like an error code to process or categorize the error being added.
message should be human-readable and detailed enough to pinpoint and resolve the problem, but it should be brief. For example, a payload of 100 objects in a JSON array might have an error in the 41st object. The message should help the end user find and fix the error with their request.
type Field ¶
type Field struct { // Form is the form field name to bind from Form string // Required indicates whether the field is required. A required // field that deserializes into the zero value for that type // will generate an error. Required bool // TimeFormat specifies the time format for time.Time fields. TimeFormat string // Binder is a function that converts the incoming request value(s) // to the field type; in other words, this field is populated // by executing this function. Useful when the custom type doesn't // implement the Binder interface. Binder func(string, []string) error // ErrorMessage allows the error the to be customized. ErrorMessage string }
Field describes the properties of a struct field.
type FieldMap ¶
type FieldMap map[interface{}]interface{}
FieldMap is a map of pointers to struct fields -> field names from the request. The values could also be Field structs to specify metadata about the field.
type FieldMapper ¶
type FieldMapper interface { // FieldMap returns a map of pointers into which the values will // be deserialized to field names from the request's form body. FieldMap(*http.Request) FieldMap }
Only types that are FieldMappers can have request data deserialized into them.
type Validator ¶
type Validator interface { // Validate validates that the request is OK. It is recommended // that validation be limited to checking values for syntax and // semantics, enough to know that you can make sense of the request // in your application. For example, you might verify that a credit // card number matches a valid pattern, but you probably wouldn't // perform an actual credit card authorization here. Validate(*http.Request) error }
Validator can be implemented by your type to handle some rudimentary request validation separately from your application logic.