Merge pull request #1581 from prometheus/vendorup

vendor: update govalidator
pull/1588/head
Brian Brazil 9 years ago
commit 816193f254

@ -42,6 +42,7 @@ func Filter(array []interface{}, iterator ConditionIterator) []interface{}
func Find(array []interface{}, iterator ConditionIterator) interface{}
func GetLine(s string, index int) (string, error)
func GetLines(s string) []string
func IsHost(s string) bool
func InRange(value, left, right float64) bool
func IsASCII(str string) bool
func IsAlpha(str string) bool
@ -50,6 +51,8 @@ func IsBase64(str string) bool
func IsByteLength(str string, min, max int) bool
func IsCreditCard(str string) bool
func IsDataURI(str string) bool
func IsDialString(str string) bool
func IsDNSName(str string) bool
func IsDivisibleBy(str, num string) bool
func IsEmail(str string) bool
func IsFilePath(str string) (bool, int)
@ -80,6 +83,7 @@ func IsNonNegative(value float64) bool
func IsNonPositive(value float64) bool
func IsNull(str string) bool
func IsNumeric(str string) bool
func IsPort(str string) bool
func IsPositive(value float64) bool
func IsPrintableASCII(str string) bool
func IsRGBcolor(str string) bool
@ -146,7 +150,7 @@ type User struct {
LastName string
}
str, _ := govalidator.ToString(&User{"John", "Juan"})
str := govalidator.ToString(&User{"John", "Juan"})
println(str)
```
###### Each, Map, Filter, Count for slices
@ -188,12 +192,15 @@ Here is a list of available validators for struct fields (validator - used funct
"base64": IsBase64,
"creditcard": IsCreditCard,
"datauri": IsDataURI,
"dialstring": IsDialString,
"dns": IsDNSName,
"email": IsEmail,
"float": IsFloat,
"fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth,
"hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor,
"host": IsHost,
"int": IsInt,
"ip": IsIP,
"ipv4": IsIPv4,
@ -208,6 +215,7 @@ Here is a list of available validators for struct fields (validator - used funct
"multibyte": IsMultibyte,
"null": IsNull,
"numeric": IsNumeric,
"port": IsPort,
"printableascii": IsPrintableASCII,
"requri": IsRequestURI,
"requrl": IsRequestURL,
@ -282,4 +290,3 @@ If you do have a contribution for the package feel free to put up a Pull Request
* [Simon ccl1115](https://github.com/ccl1115)
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/asaskevich/govalidator/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

@ -15,10 +15,15 @@ func (es Errors) Error() string {
}
type Error struct {
Name string
Err error
Name string
Err error
CustomErrorMessageExists bool
}
func (e Error) Error() string {
return e.Name + ": " + e.Err.Error()
if e.CustomErrorMessageExists {
return e.Err.Error()
} else {
return e.Name + ": " + e.Err.Error()
}
}

@ -29,7 +29,8 @@ const (
DataURI string = "^data:.+\\/(.+);base64$"
Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
URL string = `^((ftp|https?):\/\/)?(\S+(:\S*)?@)?((([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]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`
DNSName string = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{1,62}){1}(\.[a-zA-Z0-9]{1}[a-zA-Z0-9_-]{1,62})*$`
URL string = `^((ftp|https?):\/\/)?(\S+(:\S*)?@)?((([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]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([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,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`
SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$`
UnixPath string = `^((?:\/[a-zA-Z0-9\.\:]+(?:_[a-zA-Z0-9\:\.]+)*(?:\-[\:a-zA-Z0-9\.]+)*)+\/?)$`
@ -73,6 +74,7 @@ var (
rxDataURI = regexp.MustCompile(DataURI)
rxLatitude = regexp.MustCompile(Latitude)
rxLongitude = regexp.MustCompile(Longitude)
rxDNSName = regexp.MustCompile(DNSName)
rxURL = regexp.MustCompile(URL)
rxSSN = regexp.MustCompile(SSN)
rxWinPath = regexp.MustCompile(WinPath)

@ -46,6 +46,7 @@ var CustomTypeTagMap = map[string]CustomTypeValidator{}
var TagMap = map[string]Validator{
"email": IsEmail,
"url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL,
"requri": IsRequestURI,
"alpha": IsAlpha,
@ -80,8 +81,11 @@ var TagMap = map[string]Validator{
"base64": IsBase64,
"datauri": IsDataURI,
"ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4,
"ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC,
"latitude": IsLatitude,
"longitude": IsLongitude,

@ -9,7 +9,9 @@ import (
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"unicode"
"unicode/utf8"
)
@ -450,11 +452,38 @@ func IsISO3166Alpha3(str string) bool {
return false
}
// IsDNSName will validate the given string as a DNS name
func IsDNSName(str string) bool {
if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 {
// constraints already violated
return false
}
return rxDNSName.MatchString(str)
}
// IsDialString validates the given string for usage with the various Dial() functions
func IsDialString(str string) bool {
if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (IsDNSName(h) || IsIP(h)) && IsPort(p) {
return true
}
return false
}
// IsIP checks if a string is either IP version 4 or 6.
func IsIP(str string) bool {
return net.ParseIP(str) != nil
}
// IsPort checks if a string represents a valid port
func IsPort(str string) bool {
if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 {
return true
}
return false
}
// IsIPv4 check if the string is an IP version 4.
func IsIPv4(str string) bool {
ip := net.ParseIP(str)
@ -480,6 +509,11 @@ func IsMAC(str string) bool {
return err == nil
}
// IsHost checks if the string is a valid IP (both v4 and v6) or a valid DNS name
func IsHost(str string) bool {
return IsIP(str) || IsDNSName(str)
}
// IsMongoID check if the string is a valid hex-encoded representation of a MongoDB ObjectId.
func IsMongoID(str string) bool {
return rxHexadecimal.MatchString(str) && (len(str) == 24)
@ -614,19 +648,39 @@ func (opts tagOptions) contains(optionName string) bool {
return false
}
func searchOption(limit int, predicate func(counter int) bool) int {
for counter := 0; counter < limit; counter++ {
if predicate(counter) {
return counter
}
}
return -1
}
func checkRequired(v reflect.Value, t reflect.StructField, options tagOptions) (bool, error) {
if options.contains("required") {
err := fmt.Errorf("non zero value required")
return false, Error{t.Name, err}
} else if fieldsRequiredByDefault && !options.contains("optional") {
var err error
var customErrorMessageExists bool
requiredIndex := searchOption(len(options), func(index int) bool { return strings.HasPrefix(options[index], "required") })
optionalIndex := searchOption(len(options), func(index int) bool { return strings.HasPrefix(options[index], "optional") })
if requiredIndex > -1 {
validationOptions := strings.Split(options[requiredIndex], "~")
if len(validationOptions) == 2 {
err = fmt.Errorf(strings.Split(options[requiredIndex], "~")[1])
customErrorMessageExists = true
} else {
err = fmt.Errorf("non zero value required")
}
return false, Error{t.Name, err, customErrorMessageExists}
} else if fieldsRequiredByDefault && optionalIndex == -1 {
err := fmt.Errorf("All fields are required to at least have one validation defined")
return false, Error{t.Name, err}
return false, Error{t.Name, err, customErrorMessageExists}
}
// not required and empty is valid
return true, nil
}
func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
var customErrorMessageExists bool
if !v.IsValid() {
return false, nil
}
@ -640,7 +694,7 @@ func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
return true, nil
}
err := fmt.Errorf("All fields are required to at least have one validation defined")
return false, Error{t.Name, err}
return false, Error{t.Name, err, customErrorMessageExists}
case "-":
return true, nil
}
@ -648,13 +702,17 @@ func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
options := parseTag(tag)
for i := range options {
tagOpt := options[i]
if ok := isValidTag(tagOpt); !ok {
tagOptions := strings.Split(tagOpt, "~")
if ok := isValidTag(tagOptions[0]); !ok {
continue
}
if validatefunc, ok := CustomTypeTagMap[tagOpt]; ok {
if validatefunc, ok := CustomTypeTagMap[tagOptions[0]]; ok {
options = append(options[:i], options[i+1:]...) // we found our custom validator, so remove it from the options
if result := validatefunc(v.Interface()); !result {
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), tagOpt)}
if len(tagOptions) == 2 {
return false, Error{t.Name, fmt.Errorf(tagOptions[1]), true}
}
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), tagOptions[0]), false}
}
return true, nil
}
@ -674,60 +732,81 @@ func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
// for each tag option check the map of validator functions
for i := range options {
tagOpt := options[i]
tagOptions := strings.Split(tagOpt, "~")
negate := false
customMsgExists := (len(tagOptions) == 2)
// Check wether the tag looks like '!something' or 'something'
if len(tagOpt) > 0 && tagOpt[0] == '!' {
tagOpt = string(tagOpt[1:])
if len(tagOptions[0]) > 0 && tagOptions[0][0] == '!' {
tagOpt = string(tagOptions[0][1:])
tagOptions[0] = tagOpt
negate = true
}
if ok := isValidTag(tagOpt); !ok {
err := fmt.Errorf("Unknown Validator %s", tagOpt)
return false, Error{t.Name, err}
if ok := isValidTag(tagOptions[0]); !ok {
err := fmt.Errorf("Unknown Validator %s", tagOptions[0])
return false, Error{t.Name, err, false}
}
// Check for param validators
for key, value := range ParamTagRegexMap {
ps := value.FindStringSubmatch(tagOpt)
ps := value.FindStringSubmatch(tagOptions[0])
if len(ps) > 0 {
if validatefunc, ok := ParamTagMap[key]; ok {
switch v.Kind() {
case reflect.String:
field := fmt.Sprint(v) // make value into string, then validate with regex
if result := validatefunc(field, ps[1:]...); !result && !negate || result && negate {
if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) {
var err error
if !negate {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
}
} else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
}
}
return false, Error{t.Name, err}
return false, Error{t.Name, err, customMsgExists}
}
default:
//Not Yet Supported Types (Fail here!)
err := fmt.Errorf("Validator %s doesn't support kind %s", tagOpt, v.Kind())
return false, Error{t.Name, err}
err := fmt.Errorf("Validator %s doesn't support kind %s", tagOptions[0], v.Kind())
return false, Error{t.Name, err, false}
}
}
}
}
if validatefunc, ok := TagMap[tagOpt]; ok {
if validatefunc, ok := TagMap[tagOptions[0]]; ok {
switch v.Kind() {
case reflect.String:
field := fmt.Sprint(v) // make value into string, then validate with regex
if result := validatefunc(field); !result && !negate || result && negate {
var err error
if !negate {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
}
} else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
}
}
return false, Error{t.Name, err}
return false, Error{t.Name, err, customMsgExists}
}
default:
//Not Yet Supported Types (Fail here!)
err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", tagOpt, v.Kind(), v)
return false, Error{t.Name, err}
err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", tagOptions[0], v.Kind(), v)
return false, Error{t.Name, err, false}
}
}
}

@ -3,9 +3,11 @@
"ignore": "test",
"package": [
{
"checksumSHA1": "DypC2gHBVRhfPqBbsuGYgkrjvOw=",
"origin": "github.com/prometheus/prometheus/vendor/github.com/asaskevich/govalidator",
"path": "github.com/asaskevich/govalidator",
"revision": "129580890d97de923d9d9aec06cb1aa771812aff",
"revisionTime": "2015-12-29T23:28:36+03:00"
"revision": "5b6e9375cbf581a9008064f7216e816b568d6daa",
"revisionTime": "2016-04-23T17:31:43Z"
},
{
"path": "github.com/aws/aws-sdk-go/aws",
@ -313,5 +315,6 @@
"revision": "7ad95dd0798a40da1ccdff6dff35fd177b5edf40",
"revisionTime": "2015-06-24T11:29:02+01:00"
}
]
],
"rootPath": "github.com/prometheus/prometheus"
}

Loading…
Cancel
Save