mirror of https://github.com/prometheus/prometheus
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…
Reference in New Issue