Browse Source

vendor: update github.com/go-macaron/binding (#4428)

pull/4584/head
Unknwon 8 years ago
parent
commit
e1f01305d8
No known key found for this signature in database
GPG Key ID: 25B575AE3213B2B3
  1. 2
      vendor/github.com/go-macaron/binding/README.md
  2. 136
      vendor/github.com/go-macaron/binding/binding.go
  3. 6
      vendor/vendor.json

2
vendor/github.com/go-macaron/binding/README.md generated vendored

@ -1,4 +1,4 @@
# binding [![Build Status](https://travis-ci.org/go-macaron/binding.svg?branch=master)](https://travis-ci.org/go-macaron/binding) [![](http://gocover.io/_badge/github.com/go-macaron/binding)](http://gocover.io/github.com/go-macaron/binding) # binding [![Build Status](https://travis-ci.org/go-macaron/binding.svg?branch=master)](https://travis-ci.org/go-macaron/binding) [![Sourcegraph](https://sourcegraph.com/github.com/go-macaron/binding/-/badge.svg)](https://sourcegraph.com/github.com/go-macaron/binding?badge)
Middleware binding provides request data binding and validation for [Macaron](https://github.com/go-macaron/macaron). Middleware binding provides request data binding and validation for [Macaron](https://github.com/go-macaron/macaron).

136
vendor/github.com/go-macaron/binding/binding.go generated vendored

@ -22,6 +22,7 @@ import (
"io" "io"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/url"
"reflect" "reflect"
"regexp" "regexp"
"strconv" "strconv"
@ -32,7 +33,7 @@ import (
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
) )
const _VERSION = "0.3.2" const _VERSION = "0.6.0"
func Version() string { func Version() string {
return _VERSION return _VERSION
@ -145,7 +146,7 @@ func Form(formStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
if parseErr != nil { if parseErr != nil {
errors.Add([]string{}, ERR_DESERIALIZATION, parseErr.Error()) errors.Add([]string{}, ERR_DESERIALIZATION, parseErr.Error())
} }
mapForm(formStruct, ctx.Req.Form, nil, errors) errors = mapForm(formStruct, ctx.Req.Form, nil, errors)
validateAndMap(formStruct, ctx, errors, ifacePtr...) validateAndMap(formStruct, ctx, errors, ifacePtr...)
} }
} }
@ -185,7 +186,7 @@ func MultipartForm(formStruct interface{}, ifacePtr ...interface{}) macaron.Hand
ctx.Req.MultipartForm = form ctx.Req.MultipartForm = form
} }
} }
mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors) errors = mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors)
validateAndMap(formStruct, ctx, errors, ifacePtr...) validateAndMap(formStruct, ctx, errors, ifacePtr...)
} }
} }
@ -211,13 +212,35 @@ func Json(jsonStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
} }
} }
// RawValidate is same as Validate but does not require a HTTP context,
// and can be used independently just for validation.
// This function does not support Validator interface.
func RawValidate(obj interface{}) Errors {
var errs Errors
v := reflect.ValueOf(obj)
k := v.Kind()
if k == reflect.Interface || k == reflect.Ptr {
v = v.Elem()
k = v.Kind()
}
if k == reflect.Slice || k == reflect.Array {
for i := 0; i < v.Len(); i++ {
e := v.Index(i).Interface()
errs = validateStruct(errs, e)
}
} else {
errs = validateStruct(errs, obj)
}
return errs
}
// Validate is middleware to enforce required fields. If the struct // Validate is middleware to enforce required fields. If the struct
// passed in implements Validator, then the user-defined Validate method // passed in implements Validator, then the user-defined Validate method
// is executed, and its errors are mapped to the context. This middleware // is executed, and its errors are mapped to the context. This middleware
// performs no error handling: it merely detects errors and maps them. // performs no error handling: it merely detects errors and maps them.
func Validate(obj interface{}) macaron.Handler { func Validate(obj interface{}) macaron.Handler {
return func(ctx *macaron.Context) { return func(ctx *macaron.Context) {
var errors Errors var errs Errors
v := reflect.ValueOf(obj) v := reflect.ValueOf(obj)
k := v.Kind() k := v.Kind()
if k == reflect.Interface || k == reflect.Ptr { if k == reflect.Interface || k == reflect.Ptr {
@ -227,18 +250,18 @@ func Validate(obj interface{}) macaron.Handler {
if k == reflect.Slice || k == reflect.Array { if k == reflect.Slice || k == reflect.Array {
for i := 0; i < v.Len(); i++ { for i := 0; i < v.Len(); i++ {
e := v.Index(i).Interface() e := v.Index(i).Interface()
errors = validateStruct(errors, e) errs = validateStruct(errs, e)
if validator, ok := e.(Validator); ok { if validator, ok := e.(Validator); ok {
errors = validator.Validate(ctx, errors) errs = validator.Validate(ctx, errs)
} }
} }
} else { } else {
errors = validateStruct(errors, obj) errs = validateStruct(errs, obj)
if validator, ok := obj.(Validator); ok { if validator, ok := obj.(Validator); ok {
errors = validator.Validate(ctx, errors) errs = validator.Validate(ctx, errs)
} }
} }
ctx.Map(errors) ctx.Map(errs)
} }
} }
@ -246,9 +269,42 @@ var (
AlphaDashPattern = regexp.MustCompile("[^\\d\\w-_]") AlphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
AlphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]") AlphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]")
EmailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?") EmailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
URLPattern = regexp.MustCompile(`(http|https):\/\/(?:\\S+(?::\\S*)?@)?[\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?`)
) )
// Copied from github.com/asaskevich/govalidator.
const _MAX_URL_RUNE_COUNT = 2083
const _MIN_URL_RUNE_COUNT = 3
var (
urlSchemaRx = `((ftp|tcp|udp|wss?|https?):\/\/)`
urlUsernameRx = `(\S+(:\S*)?@)`
urlIPRx = `([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))`
ipRx = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
urlSubdomainRx = `((www\.)|([a-zA-Z0-9]([-\.][-\._a-zA-Z0-9]+)*))`
urlPortRx = `(:(\d{1,5}))`
urlPathRx = `((\/|\?|#)[^\s]*)`
URLPattern = regexp.MustCompile(`^` + urlSchemaRx + `?` + urlUsernameRx + `?` + `((` + urlIPRx + `|(\[` + ipRx + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + urlSubdomainRx + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + urlPortRx + `?` + urlPathRx + `?$`)
)
// IsURL check if the string is an URL.
func isURL(str string) bool {
if str == "" || utf8.RuneCountInString(str) >= _MAX_URL_RUNE_COUNT || len(str) <= _MIN_URL_RUNE_COUNT || strings.HasPrefix(str, ".") {
return false
}
u, err := url.Parse(str)
if err != nil {
return false
}
if strings.HasPrefix(u.Host, ".") {
return false
}
if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
return false
}
return URLPattern.MatchString(str)
}
type ( type (
// Rule represents a validation rule. // Rule represents a validation rule.
Rule struct { Rule struct {
@ -257,18 +313,34 @@ type (
// IsValid applies validation rule to condition. // IsValid applies validation rule to condition.
IsValid func(Errors, string, interface{}) (bool, Errors) IsValid func(Errors, string, interface{}) (bool, Errors)
} }
// RuleMapper represents a validation rule mapper,
// ParamRule does same thing as Rule but passes rule itself to IsValid method.
ParamRule struct {
// IsMatch checks if rule matches.
IsMatch func(string) bool
// IsValid applies validation rule to condition.
IsValid func(Errors, string, string, interface{}) (bool, Errors)
}
// RuleMapper and ParamRuleMapper represent validation rule mappers,
// it allwos users to add custom validation rules. // it allwos users to add custom validation rules.
RuleMapper []*Rule RuleMapper []*Rule
ParamRuleMapper []*ParamRule
) )
var ruleMapper RuleMapper var ruleMapper RuleMapper
var paramRuleMapper ParamRuleMapper
// AddRule adds new validation rule. // AddRule adds new validation rule.
func AddRule(r *Rule) { func AddRule(r *Rule) {
ruleMapper = append(ruleMapper, r) ruleMapper = append(ruleMapper, r)
} }
// AddParamRule adds new validation rule.
func AddParamRule(r *ParamRule) {
paramRuleMapper = append(paramRuleMapper, r)
}
func in(fieldValue interface{}, arr string) bool { func in(fieldValue interface{}, arr string) bool {
val := fmt.Sprintf("%v", fieldValue) val := fmt.Sprintf("%v", fieldValue)
vals := strings.Split(arr, ",") vals := strings.Split(arr, ",")
@ -356,6 +428,16 @@ VALIDATE_RULES:
break VALIDATE_RULES break VALIDATE_RULES
} }
case rule == "Required": case rule == "Required":
v := reflect.ValueOf(fieldValue)
if v.Kind() == reflect.Slice {
if v.Len() == 0 {
errors.Add([]string{field.Name}, ERR_REQUIRED, "Required")
break VALIDATE_RULES
}
continue
}
if reflect.DeepEqual(zero, fieldValue) { if reflect.DeepEqual(zero, fieldValue) {
errors.Add([]string{field.Name}, ERR_REQUIRED, "Required") errors.Add([]string{field.Name}, ERR_REQUIRED, "Required")
break VALIDATE_RULES break VALIDATE_RULES
@ -422,7 +504,7 @@ VALIDATE_RULES:
str := fmt.Sprintf("%v", fieldValue) str := fmt.Sprintf("%v", fieldValue)
if len(str) == 0 { if len(str) == 0 {
continue continue
} else if !URLPattern.MatchString(str) { } else if !isURL(str) {
errors.Add([]string{field.Name}, ERR_URL, "Url") errors.Add([]string{field.Name}, ERR_URL, "Url")
break VALIDATE_RULES break VALIDATE_RULES
} }
@ -449,14 +531,14 @@ VALIDATE_RULES:
case strings.HasPrefix(rule, "Default("): case strings.HasPrefix(rule, "Default("):
if reflect.DeepEqual(zero, fieldValue) { if reflect.DeepEqual(zero, fieldValue) {
if fieldVal.CanAddr() { if fieldVal.CanAddr() {
setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors) errors = setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors)
} else { } else {
errors.Add([]string{field.Name}, ERR_EXCLUDE, "Default") errors.Add([]string{field.Name}, ERR_EXCLUDE, "Default")
break VALIDATE_RULES break VALIDATE_RULES
} }
} }
default: default:
// Apply custom validation rules. // Apply custom validation rules
var isValid bool var isValid bool
for i := range ruleMapper { for i := range ruleMapper {
if ruleMapper[i].IsMatch(rule) { if ruleMapper[i].IsMatch(rule) {
@ -466,6 +548,14 @@ VALIDATE_RULES:
} }
} }
} }
for i := range paramRuleMapper {
if paramRuleMapper[i].IsMatch(rule) {
isValid, errors = paramRuleMapper[i].IsValid(errors, rule, field.Name, fieldValue)
if !isValid {
break VALIDATE_RULES
}
}
}
} }
} }
return errors return errors
@ -497,7 +587,7 @@ func SetNameMapper(nm NameMapper) {
// Takes values from the form data and puts them into a struct // Takes values from the form data and puts them into a struct
func mapForm(formStruct reflect.Value, form map[string][]string, func mapForm(formStruct reflect.Value, form map[string][]string,
formfile map[string][]*multipart.FileHeader, errors Errors) { formfile map[string][]*multipart.FileHeader, errors Errors) Errors {
if formStruct.Kind() == reflect.Ptr { if formStruct.Kind() == reflect.Ptr {
formStruct = formStruct.Elem() formStruct = formStruct.Elem()
@ -510,12 +600,12 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
if typeField.Type.Kind() == reflect.Ptr && typeField.Anonymous { if typeField.Type.Kind() == reflect.Ptr && typeField.Anonymous {
structField.Set(reflect.New(typeField.Type.Elem())) structField.Set(reflect.New(typeField.Type.Elem()))
mapForm(structField.Elem(), form, formfile, errors) errors = mapForm(structField.Elem(), form, formfile, errors)
if reflect.DeepEqual(structField.Elem().Interface(), reflect.Zero(structField.Elem().Type()).Interface()) { if reflect.DeepEqual(structField.Elem().Interface(), reflect.Zero(structField.Elem().Type()).Interface()) {
structField.Set(reflect.Zero(structField.Type())) structField.Set(reflect.Zero(structField.Type()))
} }
} else if typeField.Type.Kind() == reflect.Struct { } else if typeField.Type.Kind() == reflect.Struct {
mapForm(structField, form, formfile, errors) errors = mapForm(structField, form, formfile, errors)
} }
inputFieldName := parseFormName(typeField.Name, typeField.Tag.Get("form")) inputFieldName := parseFormName(typeField.Name, typeField.Tag.Get("form"))
@ -530,11 +620,11 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
sliceOf := structField.Type().Elem().Kind() sliceOf := structField.Type().Elem().Kind()
slice := reflect.MakeSlice(structField.Type(), numElems, numElems) slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
for i := 0; i < numElems; i++ { for i := 0; i < numElems; i++ {
setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors) errors = setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
} }
formStruct.Field(i).Set(slice) formStruct.Field(i).Set(slice)
} else { } else {
setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors) errors = setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors)
} }
continue continue
} }
@ -555,13 +645,14 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
structField.Set(reflect.ValueOf(inputFile[0])) structField.Set(reflect.ValueOf(inputFile[0]))
} }
} }
return errors
} }
// This sets the value in a struct of an indeterminate type to the // This sets the value in a struct of an indeterminate type to the
// matching value from the request (via Form middleware) in the // matching value from the request (via Form middleware) in the
// same type, so that not all deserialized values have to be strings. // same type, so that not all deserialized values have to be strings.
// Supported types are string, int, float, and bool. // Supported types are string, int, float, and bool.
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) { func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) Errors {
switch valueKind { switch valueKind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if val == "" { if val == "" {
@ -586,7 +677,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
case reflect.Bool: case reflect.Bool:
if val == "on" { if val == "on" {
structField.SetBool(true) structField.SetBool(true)
return break
} }
if val == "" { if val == "" {
@ -621,6 +712,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
case reflect.String: case reflect.String:
structField.SetString(val) structField.SetString(val)
} }
return errors
} }
// Don't pass in pointers to bind to. Can lead to bugs. // Don't pass in pointers to bind to. Can lead to bugs.

6
vendor/vendor.json vendored

@ -75,10 +75,10 @@
"revisionTime": "2017-01-13T15:16:12Z" "revisionTime": "2017-01-13T15:16:12Z"
}, },
{ {
"checksumSHA1": "qM/kf31cT2cxjtHxdzbu8q8jPq0=", "checksumSHA1": "J0tcl2i76AQvMio9MWNQaucepYA=",
"path": "github.com/go-macaron/binding", "path": "github.com/go-macaron/binding",
"revision": "9440f336b443056c90d7d448a0a55ad8c7599880", "revision": "ac54ee249c27dca7e76fad851a4a04b73bd1b183",
"revisionTime": "2016-07-11T22:56:54Z" "revisionTime": "2017-06-11T06:58:19Z"
}, },
{ {
"checksumSHA1": "6pSblXcT+pZJWhPCEyLZONiQUHg=", "checksumSHA1": "6pSblXcT+pZJWhPCEyLZONiQUHg=",

Loading…
Cancel
Save