A powerful HTTP request parameters binder that supports struct tag expression.
func Example() {
type InfoRequest struct {
Name string `path:"name"`
Year []int `query:"year"`
Email *string `json:"email" vd:"email($)"`
Friendly bool `json:"friendly"`
Status string `json:"status" default:"single"`
Pie float32 `json:"pie,required"`
Hobby []string `json:",required"`
BodyNotFound *int `json:"BodyNotFound"`
Authorization string `header:"Authorization,required" vd:"$=='Basic 123456'"`
SessionID string `cookie:"sessionid,required"`
AutoBody string
AutoNotFound *string
TimeRFC3339 time.Time `query:"t"`
}
args := new(InfoRequest)
binder := binding.New(nil)
err := binder.BindAndValidate(args, requestExample(), new(testPathParams))
fmt.Println("bind and validate result:")
fmt.Printf("error: %v\n", err)
b, _ := json.MarshalIndent(args, "", " ")
fmt.Printf("args JSON string:\n%s\n", b)
// Output:
// request:
// POST /info/henrylee2cn?year=2018&year=2019&t=2019-09-04T18:04:08+08:00 HTTP/1.1
// Host: localhost
// User-Agent: Go-http-client/1.1
// Transfer-Encoding: chunked
// Authorization: Basic 123456
// Content-Type: application/json;charset=utf-8
// Cookie: sessionid=987654
//
// 83
// {"AutoBody":"autobody_test","Hobby":["Coding","Mountain climbing"],"email":"[email protected]","friendly":true,"pie":3.1415926}
// 0
//
// bind and validate result:
// error: <nil>
// args JSON string:
// {
// "Name": "henrylee2cn",
// "Year": [
// 2018,
// 2019
// ],
// "email": "[email protected]",
// "friendly": true,
// "status": "single",
// "pie": 3.1415925,
// "Hobby": [
// "Coding",
// "Mountain climbing"
// ],
// "BodyNotFound": null,
// "Authorization": "Basic 123456",
// "SessionID": "987654",
// "AutoBody": "autobody_test",
// "AutoNotFound": null,
// "TimeRFC3339": "2019-09-04T18:04:08 08:00"
// }
}
...
The parameter position in HTTP request:
expression | renameable | description |
---|---|---|
path:"$name" or path:"$name,required" |
Yes | URL path parameter |
query:"$name" or query:"$name,required" |
Yes | URL query parameter |
raw_body:"" or raw_body:"required" |
Yes | The raw bytes of body |
form:"$name" or form:"$name,required" |
Yes | The field in body, support:application/x-www-form-urlencoded ,multipart/form-data |
protobuf:"...(raw syntax)" |
No | The field in body, support:application/x-protobuf |
json:"$name" or json:"$name,required" |
No | The field in body, support:application/json |
header:"$name" or header:"$name,required" |
Yes | Header parameter |
cookie:"$name" or cookie:"$name,required" |
Yes | Cookie parameter |
default:"$value" |
Yes | Default parameter |
vd:"...(tagexpr validator syntax)" |
Yes | The tagexpr expression of validator |
NOTE:
"$name"
is variable placeholder- If
"$name"
is empty, use the name of field - If
"$name"
is-
, omit the field - Expression
required
orreq
indicates that the parameter is required default:"$value"
defines the default value for fallback when no binding is successful- If no position is tagged, try bind parameters from the body when the request has body,
otherwise try bind from the URL query - When there is unexportable and no tags, omit the field
- When there are multiple tags, or exportable and no tags, the order in which to try to bind is:
- path
- form
- query
- cookie
- header
- protobuf
- json
- default
TimeRFC3339-binding function is registered by default.
Register your own binding function for the specified type, e.g.:
MustRegTypeUnmarshal(reflect.TypeOf(time.Time{}), func(v string, emptyAsZero bool) (reflect.Value, error) {
if v == "" && emptyAsZero {
return reflect.ValueOf(time.Time{}), nil
}
t, err := time.Parse(time.RFC3339, v)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(t), nil
})