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.
