mirror of
https://github.com/kataras/iris.git
synced 2025-03-21 18:36:27 +01:00
improvements to the x/errors pkg
This commit is contained in:
parent
b8e84ec576
commit
fc2f8f4776
|
@ -49,6 +49,7 @@
|
||||||
* [Basic](routing/basic/main.go)
|
* [Basic](routing/basic/main.go)
|
||||||
* [Custom HTTP Errors](routing/http-errors/main.go)
|
* [Custom HTTP Errors](routing/http-errors/main.go)
|
||||||
* [HTTP Wire Errors](routing/http-wire-errors/main.go) **NEW**
|
* [HTTP Wire Errors](routing/http-wire-errors/main.go) **NEW**
|
||||||
|
* [Custom Validation Errors](routing/http-wire-errors/custom-validation-errors/main.go)
|
||||||
* [Not Found - Intelligence](routing/intelligence/main.go)
|
* [Not Found - Intelligence](routing/intelligence/main.go)
|
||||||
* [Not Found - Suggest Closest Paths](routing/intelligence/manual/main.go)
|
* [Not Found - Suggest Closest Paths](routing/intelligence/manual/main.go)
|
||||||
* [Dynamic Path](routing/dynamic-path/main.go)
|
* [Dynamic Path](routing/dynamic-path/main.go)
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/v12"
|
||||||
|
"github.com/kataras/iris/v12/x/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := newApp()
|
||||||
|
app.Listen(":8080")
|
||||||
|
}
|
||||||
|
|
||||||
|
func newApp() *iris.Application {
|
||||||
|
app := iris.New()
|
||||||
|
app.Get("/", fireCustomValidationError)
|
||||||
|
app.Get("/multi", fireCustomValidationErrors)
|
||||||
|
app.Get("/invalid", fireInvalidError)
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
type MyValidationError struct {
|
||||||
|
Field string `json:"field"`
|
||||||
|
Value interface{} `json:"value"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err MyValidationError) Error() string {
|
||||||
|
return fmt.Sprintf("field %q got invalid value of %v: reason: %s", err.Field, err.Value, err.Reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error, GetField, GetValue and GetReason completes
|
||||||
|
// the x/errors.ValidationError interface which can be used
|
||||||
|
// for faster rendering without the necessity of registering a custom
|
||||||
|
// type (see at the end of the example).
|
||||||
|
//
|
||||||
|
// func (err MyValidationError) GetField() string {
|
||||||
|
// return err.Field
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (err MyValidationError) GetValue() interface{} {
|
||||||
|
// return err.Value
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (err MyValidationError) GetReason() string {
|
||||||
|
// return err.Reason
|
||||||
|
// }
|
||||||
|
|
||||||
|
const shouldFail = true
|
||||||
|
|
||||||
|
func fireCustomValidationError(ctx iris.Context) {
|
||||||
|
if shouldFail {
|
||||||
|
err := MyValidationError{
|
||||||
|
Field: "username",
|
||||||
|
Value: "",
|
||||||
|
Reason: "empty string",
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// The "validation" field, when used, is always rendering as
|
||||||
|
// a JSON array, NOT a single object.
|
||||||
|
errors.InvalidArgument.Err(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.WriteString("OK")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally register custom types that you may need
|
||||||
|
// to be rendered as validation errors if the given "ErrorCodeName.Err.err"
|
||||||
|
// input parameter is matched with one of these. Register once, at initialiation.
|
||||||
|
func init() {
|
||||||
|
mapper := errors.NewValidationErrorTypeMapper(MyValidationError{} /*, OtherCustomType{} */)
|
||||||
|
errors.RegisterValidationErrorMapper(mapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A custom type of the example validation error type
|
||||||
|
// in order to complete the error interface, so it can be
|
||||||
|
// pass through the errors.InvalidArgument.Err method.
|
||||||
|
type MyValidationErrors []MyValidationError
|
||||||
|
|
||||||
|
func (m MyValidationErrors) Error() string {
|
||||||
|
return "to be an error"
|
||||||
|
}
|
||||||
|
|
||||||
|
func fireCustomValidationErrors(ctx iris.Context) {
|
||||||
|
if shouldFail {
|
||||||
|
errs := MyValidationErrors{
|
||||||
|
{
|
||||||
|
Field: "username",
|
||||||
|
Value: "",
|
||||||
|
Reason: "empty string",
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Field: "birth_date",
|
||||||
|
Value: "2022-01-01",
|
||||||
|
Reason: "too young",
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
errors.InvalidArgument.Err(ctx, errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.WriteString("OK")
|
||||||
|
}
|
||||||
|
|
||||||
|
func fireInvalidError(ctx iris.Context) {
|
||||||
|
if shouldFail {
|
||||||
|
errors.InvalidArgument.Err(ctx, fmt.Errorf("just a custom error text"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.WriteString("OK")
|
||||||
|
}
|
|
@ -912,7 +912,7 @@ type Configuration struct {
|
||||||
Other map[string]interface{} `ini:"other" json:"other,omitempty" yaml:"Other" toml:"Other"`
|
Other map[string]interface{} `ini:"other" json:"other,omitempty" yaml:"Other" toml:"Other"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ context.ConfigurationReadOnly = &Configuration{}
|
var _ context.ConfigurationReadOnly = (*Configuration)(nil)
|
||||||
|
|
||||||
// GetVHost returns the non-exported vhost config field.
|
// GetVHost returns the non-exported vhost config field.
|
||||||
func (c Configuration) GetVHost() string {
|
func (c Configuration) GetVHost() string {
|
||||||
|
|
|
@ -134,9 +134,13 @@ func (e ErrorCodeName) DataWithDetails(ctx iris.Context, msg, details string, da
|
||||||
fail(ctx, e, msg, details, nil, data)
|
fail(ctx, e, msg, details, nil, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation sends an error which contains the invalid fields to the client.
|
// Validation sends an error which renders the invalid fields to the client.
|
||||||
func (e ErrorCodeName) Validation(ctx iris.Context, errs ...ValidationError) {
|
func (e ErrorCodeName) Validation(ctx iris.Context, validationErrors ...ValidationError) {
|
||||||
fail(ctx, e, "validation failure", "fields were invalid", errs, nil)
|
e.validation(ctx, validationErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrorCodeName) validation(ctx iris.Context, validationErrors interface{}) {
|
||||||
|
fail(ctx, e, "validation failure", "fields were invalid", validationErrors, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err sends the error's text as a message to the client.
|
// Err sends the error's text as a message to the client.
|
||||||
|
@ -148,7 +152,7 @@ func (e ErrorCodeName) Err(ctx iris.Context, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if validationErrors, ok := AsValidationErrors(err); ok {
|
if validationErrors, ok := AsValidationErrors(err); ok {
|
||||||
e.Validation(ctx, validationErrors...)
|
e.validation(ctx, validationErrors)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,12 +235,15 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error represents the JSON form of "http wire errors".
|
// Error represents the JSON form of "http wire errors".
|
||||||
|
//
|
||||||
|
// Examples can be found at:
|
||||||
|
// https://github.com/kataras/iris/tree/master/_examples/routing/http-wire-errors.
|
||||||
type Error struct {
|
type Error struct {
|
||||||
ErrorCode ErrorCode `json:"http_error_code" yaml:"HTTPErrorCode"`
|
ErrorCode ErrorCode `json:"http_error_code" yaml:"HTTPErrorCode"`
|
||||||
Message string `json:"message,omitempty" yaml:"Message"`
|
Message string `json:"message,omitempty" yaml:"Message"`
|
||||||
Details string `json:"details,omitempty" yaml:"Details"`
|
Details string `json:"details,omitempty" yaml:"Details"`
|
||||||
ValidationErrors ValidationErrors `json:"validation,omitempty" yaml:"Validation,omitempty"`
|
Validation interface{} `json:"validation,omitempty" yaml:"Validation,omitempty"`
|
||||||
Data json.RawMessage `json:"data,omitempty" yaml:"Data,omitempty"` // any other custom json data.
|
Data json.RawMessage `json:"data,omitempty" yaml:"Data,omitempty"` // any other custom json data.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error method completes the error interface. It just returns the canonical name, status code, message and details.
|
// Error method completes the error interface. It just returns the canonical name, status code, message and details.
|
||||||
|
@ -260,7 +267,7 @@ func (err Error) Error() string {
|
||||||
return sprintf("iris http wire error: canonical name: %s, http status code: %d, message: %s, details: %s", err.ErrorCode.CanonicalName, err.ErrorCode.Status, err.Message, err.Details)
|
return sprintf("iris http wire error: canonical name: %s, http status code: %d, message: %s, details: %s", err.ErrorCode.CanonicalName, err.ErrorCode.Status, err.Message, err.Details)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fail(ctx iris.Context, codeName ErrorCodeName, msg, details string, validationErrors ValidationErrors, dataValue interface{}) {
|
func fail(ctx iris.Context, codeName ErrorCodeName, msg, details string, validationErrors interface{}, dataValue interface{}) {
|
||||||
errorCode, ok := errorCodeMap[codeName]
|
errorCode, ok := errorCodeMap[codeName]
|
||||||
if !ok {
|
if !ok {
|
||||||
// This SHOULD NEVER happen, all ErrorCodeNames MUST be registered.
|
// This SHOULD NEVER happen, all ErrorCodeNames MUST be registered.
|
||||||
|
@ -297,11 +304,11 @@ func fail(ctx iris.Context, codeName ErrorCodeName, msg, details string, validat
|
||||||
}
|
}
|
||||||
|
|
||||||
err := Error{
|
err := Error{
|
||||||
ErrorCode: errorCode,
|
ErrorCode: errorCode,
|
||||||
Message: msg,
|
Message: msg,
|
||||||
Details: details,
|
Details: details,
|
||||||
Data: data,
|
Data: data,
|
||||||
ValidationErrors: validationErrors,
|
Validation: validationErrors,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ctx.SetErr(err)
|
// ctx.SetErr(err)
|
||||||
|
|
|
@ -1,56 +1,32 @@
|
||||||
package errors
|
package errors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"reflect"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AsValidationErrors reports wheether the given "err" is a type of validation error(s).
|
// ValidationError is an interface which IF
|
||||||
func AsValidationErrors(err error) (ValidationErrors, bool) {
|
// it custom error types completes, then
|
||||||
if err == nil {
|
// it can by mapped to a validation error.
|
||||||
return nil, false
|
//
|
||||||
}
|
// A validation error(s) can be given by ErrorCodeName's Validation or Err methods.
|
||||||
|
//
|
||||||
|
// Example can be found at:
|
||||||
|
// https://github.com/kataras/iris/tree/master/_examples/routing/http-wire-errors/custom-validation-errors
|
||||||
|
type ValidationError interface {
|
||||||
|
error
|
||||||
|
|
||||||
switch e := err.(type) {
|
GetField() string
|
||||||
case ValidationError:
|
GetValue() interface{}
|
||||||
return ValidationErrors{e}, true
|
GetReason() string
|
||||||
case ValidationErrors:
|
|
||||||
return e, true
|
|
||||||
case *ValidationErrors:
|
|
||||||
return *e, true
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueValidator is a generic interface which can be used to check if the value is valid for insert (or for comparison inside another validation step).
|
|
||||||
// Useful for enums.
|
|
||||||
// Should return a non-empty string on validation error, that string is the failure reason.
|
|
||||||
type ValueValidator interface {
|
|
||||||
Validate() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidationError describes a field validation error.
|
|
||||||
type ValidationError struct {
|
|
||||||
Field string `json:"field" yaml:"Field"`
|
|
||||||
Value interface{} `json:"value" yaml:"Value"`
|
|
||||||
Reason string `json:"reason" yaml:"Reason"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error completes the standard error interface.
|
|
||||||
func (e ValidationError) Error() string {
|
|
||||||
return sprintf("field %q got invalid value of %v: reason: %s", e.Field, e.Value, e.Reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidationErrors is just a custom type of ValidationError slice.
|
|
||||||
type ValidationErrors []ValidationError
|
type ValidationErrors []ValidationError
|
||||||
|
|
||||||
// Error completes the error interface.
|
func (errs ValidationErrors) Error() string {
|
||||||
func (e ValidationErrors) Error() string {
|
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
for i, err := range e {
|
for i, err := range errs {
|
||||||
buf.WriteByte('[')
|
buf.WriteByte('[')
|
||||||
buf.WriteString(strconv.Itoa(i))
|
buf.WriteString(strconv.Itoa(i))
|
||||||
buf.WriteByte(']')
|
buf.WriteByte(']')
|
||||||
|
@ -58,7 +34,7 @@ func (e ValidationErrors) Error() string {
|
||||||
|
|
||||||
buf.WriteString(err.Error())
|
buf.WriteString(err.Error())
|
||||||
|
|
||||||
if i < len(e)-1 {
|
if i < len(errs)-1 {
|
||||||
buf.WriteByte(',')
|
buf.WriteByte(',')
|
||||||
buf.WriteByte(' ')
|
buf.WriteByte(' ')
|
||||||
}
|
}
|
||||||
|
@ -67,115 +43,122 @@ func (e ValidationErrors) Error() string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is reports whether the given "err" is a type of validation error or validation errors.
|
// ValidationErrorMapper is the interface which
|
||||||
func (e ValidationErrors) Is(err error) bool {
|
// custom validation error mappers should complete.
|
||||||
|
type ValidationErrorMapper interface {
|
||||||
|
// The implementation must check the given "err"
|
||||||
|
// and make decision if it's an error of validation
|
||||||
|
// and if so it should return the value (err or another one)
|
||||||
|
// and true as the last output argument.
|
||||||
|
//
|
||||||
|
// Outputs:
|
||||||
|
// 1. the validation error(s) value
|
||||||
|
// 2. true if the interface{} is an array, otherise false
|
||||||
|
// 3. true if it's a validation error or false if not.
|
||||||
|
MapValidationErrors(err error) (interface{}, bool, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidationErrorMapperFunc is an "ValidationErrorMapper" but in type of a function.
|
||||||
|
type ValidationErrorMapperFunc func(err error) (interface{}, bool, bool)
|
||||||
|
|
||||||
|
// MapValidationErrors completes the "ValidationErrorMapper" interface.
|
||||||
|
func (v ValidationErrorMapperFunc) MapValidationErrors(err error) (interface{}, bool, bool) {
|
||||||
|
return v(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read-only at serve time, holds the validation error mappers.
|
||||||
|
var validationErrorMappers []ValidationErrorMapper = []ValidationErrorMapper{
|
||||||
|
ValidationErrorMapperFunc(func(err error) (interface{}, bool, bool) {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case ValidationError:
|
||||||
|
return e, false, true
|
||||||
|
case ValidationErrors:
|
||||||
|
return e, true, true
|
||||||
|
default:
|
||||||
|
return nil, false, false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterValidationErrorMapper registers a custom
|
||||||
|
// implementation of validation error mapping.
|
||||||
|
// Call it on program initilization, main() or init() functions.
|
||||||
|
func RegisterValidationErrorMapper(m ValidationErrorMapper) {
|
||||||
|
validationErrorMappers = append(validationErrorMappers, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterValidationErrorMapperFunc registers a custom
|
||||||
|
// function implementation of validation error mapping.
|
||||||
|
// Call it on program initilization, main() or init() functions.
|
||||||
|
func RegisterValidationErrorMapperFunc(fn func(err error) (interface{}, bool, bool)) {
|
||||||
|
validationErrorMappers = append(validationErrorMappers, ValidationErrorMapperFunc(fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
type validationErrorTypeMapper struct {
|
||||||
|
types []reflect.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ ValidationErrorMapper = (*validationErrorTypeMapper)(nil)
|
||||||
|
|
||||||
|
func (v *validationErrorTypeMapper) MapValidationErrors(err error) (interface{}, bool, bool) {
|
||||||
|
errType := reflect.TypeOf(err)
|
||||||
|
for _, typ := range v.types {
|
||||||
|
if equalTypes(errType, typ) {
|
||||||
|
return err, false, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// a slice is given but the underline type is registered.
|
||||||
|
if errType.Kind() == reflect.Slice {
|
||||||
|
if equalTypes(errType.Elem(), typ) {
|
||||||
|
return err, true, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func equalTypes(err reflect.Type, binding reflect.Type) bool {
|
||||||
|
return err == binding
|
||||||
|
// return binding.AssignableTo(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewValidationErrorTypeMapper returns a validation error mapper
|
||||||
|
// which compares the error with one or more of the given "types",
|
||||||
|
// through reflection. Each of the given types MUST complete the
|
||||||
|
// standard error type, so it can be passed through the error code.
|
||||||
|
func NewValidationErrorTypeMapper(types ...error) ValidationErrorMapper {
|
||||||
|
typs := make([]reflect.Type, 0, len(types))
|
||||||
|
for _, typ := range types {
|
||||||
|
v, ok := typ.(reflect.Type)
|
||||||
|
if !ok {
|
||||||
|
v = reflect.TypeOf(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
typs = append(typs, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validationErrorTypeMapper{
|
||||||
|
types: typs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsValidationErrors reports wheether the given "err" is a type of validation error(s).
|
||||||
|
// Its behavior can be modified before serve-time
|
||||||
|
// through the "RegisterValidationErrorMapper" function.
|
||||||
|
func AsValidationErrors(err error) (interface{}, bool) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch err.(type) {
|
for _, m := range validationErrorMappers {
|
||||||
case ValidationError:
|
if errs, isArray, ok := m.MapValidationErrors(err); ok {
|
||||||
return true
|
if !isArray { // ensure always-array on Validation field of the http error.
|
||||||
case *ValidationError:
|
return []interface{}{errs}, true
|
||||||
return true
|
}
|
||||||
case ValidationErrors:
|
return errs, true
|
||||||
return true
|
}
|
||||||
case *ValidationErrors:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return nil, false
|
||||||
// Add is a helper for appending a validation error.
|
|
||||||
func (e *ValidationErrors) Add(err ValidationError) *ValidationErrors {
|
|
||||||
if err.Field == "" || err.Reason == "" {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
*e = append(*e, err)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join joins an existing Errors to this errors list.
|
|
||||||
func (e *ValidationErrors) Join(errs ValidationErrors) *ValidationErrors {
|
|
||||||
*e = append(*e, errs...)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate returns the result of the value's Validate method, if exists otherwise
|
|
||||||
// it adds the field and value to the error list and reports false (invalidated).
|
|
||||||
// If reason is empty, means that the field is valid, this method will return true.
|
|
||||||
func (e *ValidationErrors) Validate(field string, value interface{}) bool {
|
|
||||||
var reason string
|
|
||||||
|
|
||||||
if v, ok := value.(ValueValidator); ok {
|
|
||||||
reason = v.Validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
if reason != "" {
|
|
||||||
e.Add(ValidationError{
|
|
||||||
Field: field,
|
|
||||||
Value: value,
|
|
||||||
Reason: reason,
|
|
||||||
})
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustBeSatisfiedFunc compares the value with the given "isEqualFunc" function and reports
|
|
||||||
// if it's valid or not. If it's not valid, a new ValidationError is added to the "e" list.
|
|
||||||
func (e *ValidationErrors) MustBeSatisfiedFunc(field string, value string, isEqualFunc func(string) bool) bool {
|
|
||||||
if !isEqualFunc(value) {
|
|
||||||
e.Add(ValidationError{
|
|
||||||
Field: field,
|
|
||||||
Value: value,
|
|
||||||
Reason: "failed to satisfy constraint",
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustBeSatisfied compares the value with the given regex and reports
|
|
||||||
// if it's valid or not. If it's not valid, a new ValidationError is added to the "e" list.
|
|
||||||
func (e *ValidationErrors) MustBeSatisfied(field string, value string, regex *regexp.Regexp) bool {
|
|
||||||
return e.MustBeSatisfiedFunc(field, value, regex.MatchString)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustBeNotEmptyString reports and fails if the given "value" is empty.
|
|
||||||
func (e *ValidationErrors) MustBeNotEmptyString(field string, value string) bool {
|
|
||||||
if strings.TrimSpace(value) == "" {
|
|
||||||
e.Add(ValidationError{
|
|
||||||
Field: field,
|
|
||||||
Value: value,
|
|
||||||
Reason: "must be not an empty string",
|
|
||||||
})
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustBeInRangeString reports whether the "value" is in range of min and max.
|
|
||||||
func (e *ValidationErrors) MustBeInRangeString(field string, value string, minIncluding, maxIncluding int) bool {
|
|
||||||
if maxIncluding <= 0 {
|
|
||||||
maxIncluding = math.MaxInt32
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(value) < minIncluding || len(value) > maxIncluding {
|
|
||||||
e.Add(ValidationError{
|
|
||||||
Field: field,
|
|
||||||
Value: value,
|
|
||||||
Reason: sprintf("characters length must be between %d and %d", minIncluding, maxIncluding),
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user