zgo.at/zvalidate Index | Examples | Files

package zvalidate

import "zgo.at/zvalidate"

Package zvalidate provides simple validation for Go.

See the README.markdown for an introduction.

Example

Code:

email := "martin@arp42.net"

v := zvalidate.New()
v.Required("email", email)
m := v.Email("email", email)

if v.HasErrors() {
    fmt.Printf("Had the following validation errors:\n%s", v)
}

fmt.Printf("parsed email: %s\n", m.Address)

Output:

parsed email: martin@arp42.net

Index

Examples

Package Files

messages.go punycode.go template.go utf8.go validators.go zvalidate.go

Variables

var (
    AlphaNumeric = &unicode.RangeTable{
        R16:         []unicode.Range16{{0x0030, 0x0039, 1}, {0x0041, 0x005a, 1}, {0x0061, 0x007a, 1}},
        LatinOffset: 3,
    }
    ASCII = &unicode.RangeTable{
        R16:         []unicode.Range16{{0x0020, 0x007e, 1}},
        LatinOffset: 1,
    }
)

Range tables for Contains()

TODO: move to zstd/zunicode?

var DefaultMessages = Messages{
    Required:    func() string { return "must be set" },
    Domain:      func() string { return "must be a valid domain" },
    Hostname:    func() string { return "must be a valid hostname" },
    URL:         func() string { return "must be a valid url" },
    Email:       func() string { return "must be a valid email address" },
    IPv4:        func() string { return "must be a valid IPv4 address" },
    IP:          func() string { return "must be a valid IPv4 or IPv6 address" },
    HexColor:    func() string { return "must be a valid color code" },
    LenLonger:   func() string { return "must be longer than %d characters" },
    LenShorter:  func() string { return "must be shorter than %d characters" },
    Exclude:     func() string { return "cannot be ‘%s’" },
    Include:     func() string { return "must be one of ‘%s’" },
    Integer:     func() string { return "must be a whole number" },
    Bool:        func() string { return "must be a boolean" },
    Date:        func() string { return "must be a date as ‘%s’" },
    Phone:       func() string { return "must be a valid phone number" },
    RangeHigher: func() string { return "must be %d or higher" },
    RangeLower:  func() string { return "must be %d or lower" },
    UTF8:        func() string { return "must be UTF-8" },
    Contains:    func() string { return "cannot contain the characters %s" },
}

func TemplateError

func TemplateError(k string, v *Validator) template.HTML

TemplateError displays validation errors for the given key.

This will Pop() errors and modify the Validator in-place, so we can see if there are any "hidden" errors later on.

Example

Code:

funcs := template.FuncMap{
    "validate":   zvalidate.TemplateError,
    "has_errors": zvalidate.TemplateHasErrors,
}

t := template.Must(template.New("").Funcs(funcs).Parse(`
<input name="xxx">
{{validate "xxx" .Validate}}

{{if has_errors .Validate}}Hidden: {{.Validate.HTML}}{{end}}
	`))

v := zvalidate.New()
v.Append("xxx", "oh noes")
v.Append("hidden", "sneaky")

t.Execute(os.Stdout, map[string]interface{}{
    "Validate": &v,
})

Output:

<input name="xxx">
<span class="err">Error: oh noes</span>

Hidden: <ul class='zvalidate'>
<li><strong>hidden</strong>: sneaky.</li>
</ul>

func TemplateHasErrors

func TemplateHasErrors(v *Validator) bool

TemplateHasErrors reports if there are any validation errors.

This is useful because "and" evaluates all arguments, and this will error out:

{{if and .Validate .Validate.HasErrors}}

type Messages

type Messages struct {
    Required    func() string
    Domain      func() string
    Hostname    func() string
    URL         func() string
    Email       func() string
    IPv4        func() string
    IP          func() string
    HexColor    func() string
    LenLonger   func() string
    LenShorter  func() string
    Exclude     func() string
    Include     func() string
    Integer     func() string
    Bool        func() string
    Date        func() string
    Phone       func() string
    RangeHigher func() string
    RangeLower  func() string
    UTF8        func() string
    Contains    func() string
}

type Validator

type Validator struct {
    Errors map[string][]string `json:"errors"`
    // contains filtered or unexported fields
}

Validator hold the validation errors.

Typically you shouldn't create this directly but use the New() function.

func As

func As(err error) *Validator

As tries to convert this error to a Validator, returning nil if it's not.

func New

func New() Validator

New initializes a new Validator.

func (*Validator) Append

func (v *Validator) Append(key, value string, format ...interface{})

Append a new error.

func (*Validator) Boolean

func (v *Validator) Boolean(key, value string, message ...string) bool

Boolean parses as string as a boolean.

func (Validator) Code

func (v Validator) Code() int

Code returns the HTTP status code for the error. Satisfies the guru.coder interface in zgo.at/guru.

func (*Validator) Contains

func (v *Validator) Contains(key, value string, ranges []*unicode.RangeTable, runes []rune, message ...string)

Contains validates that this string only contains the given characters.

This implies the UTF8() validation.

The value is in either the unicode range or runes list. For example:

zvalidate.Contains("key", val, zvalidate.AlphaNumeric, []rune{'_', '-'})

Will allow all ASCII letters and numbers and '_' and '-'.

If you have a lot of values it's faster to create a custom RangeTable.

Useful ranges:

zvalidate.AlphaNumeric    a-0A-Za-z
zvalidate.ASCII           All ASCII characters except control characters.
unicode.Letter            Any "letter" (in any script)
unicode.Number            Any "number" (in any script)
unicode.ASCII_Hex_Digit   0-9A-Fa-f

func (*Validator) Date

func (v *Validator) Date(key, value, layout string, message ...string) time.Time

Date parses a string in the given date layout.

func (*Validator) Domain

func (v *Validator) Domain(key, value string, message ...string) []string

Domain parses a domain as individual labels.

A domain must consist of at least two labels. So "com" or "localhost" – while technically valid domain names – are not accepted, whereas "example.com" or "me.localhost" are. For the overwhelming majority of applications this makes the most sense.

This works for internationalized domain names (IDN), either as UTF-8 characters or as punycode.

func (*Validator) Email

func (v *Validator) Email(key, value string, message ...string) mail.Address

Email parses an email address.

func (Validator) Error

func (v Validator) Error() string

Error interface.

func (Validator) ErrorJSON

func (v Validator) ErrorJSON() ([]byte, error)

ErrorJSON for reporting errors as JSON.

func (*Validator) ErrorOrNil

func (v *Validator) ErrorOrNil() error

ErrorOrNil returns nil if there are no errors, or the Validator object if there are.

This makes it a bit more elegant to return from a function:

if v.HasErrors() {
    return v
}
return nil

Can now be:

return v.ErrorOrNil()

func (*Validator) Exclude

func (v *Validator) Exclude(key, value string, exclude []string, message ...string) string

Exclude validates that the value is not in the exclude list.

This list is matched case-insensitive and with leading/trailing whitespace ignored. The returned value is the same as the input value.

func (*Validator) HTML

func (v *Validator) HTML() template.HTML

HTML representation of all errors, or a blank string if there are none.

func (*Validator) HasErrors

func (v *Validator) HasErrors() bool

HasErrors reports if this validation has any errors.

func (*Validator) HexColor

func (v *Validator) HexColor(key, value string, message ...string) (uint8, uint8, uint8)

HexColor parses a color as a hex triplet (e.g. #ffffff or #fff).

func (*Validator) Hostname

func (v *Validator) Hostname(key, value string, message ...string) []string

Hostname checks if this is a valid hostname.

This is different from Domain in that it considers any hostname valid, whereas Domain() is a bit stricter and validates if this is likely to be a publicly accessible domain. e.g. "localhost" is valid in Hostname(), but not Domain().

func (*Validator) IP

func (v *Validator) IP(key, value string, message ...string) net.IP

IP parses an IPv4 or IPv6 address.

func (*Validator) IPv4

func (v *Validator) IPv4(key, value string, message ...string) net.IP

IPv4 parses an IPv4 address.

func (*Validator) Include

func (v *Validator) Include(key, value string, include []string, message ...string) string

Include validates that the value is in the include list.

This list is matched case-insensitive and with leading/trailing whitespace ignored. The returned value is the "sanitized" value that matched.

func (*Validator) Integer

func (v *Validator) Integer(key, value string, message ...string) int64

Integer parses a string as an integer.

func (*Validator) Len

func (v *Validator) Len(key, value string, min, max int, message ...string) int

Len validates the character (rune) length of a string.

A maximum of 0 indicates there is no upper limit.

func (*Validator) Merge

func (v *Validator) Merge(other Validator)

Merge errors from another validator in to this one.

func (*Validator) Messages

func (v *Validator) Messages(m Messages)

Messages sets the messages to use for validation errors.

func (*Validator) Phone

func (v *Validator) Phone(key, value string, message ...string) string

Phone parses a phone number.

There are a great amount of writing conventions for phone numbers: https://en.wikipedia.org/wiki/National_conventions_for_writing_telephone_numbers

This merely checks a field contains 5 to 20 characters "0123456789+\-() .", which is not very strict but should cover all conventions.

Returns the phone number with grouping/spacing characters removed.

func (*Validator) Pop

func (v *Validator) Pop(key string) []string

Pop an error, removing all errors for this key.

This is mostly useful when displaying errors next to forms: Pop() all the errors you want to display, and then display anything that's left with a flash message or the like. This prevents "hidden" errors.

Returns nil if there are no errors for this key.

func (*Validator) Range

func (v *Validator) Range(key string, value, min, max int64, message ...string)

Range sets the minimum and maximum value of a integer.

A maximum of 0 indicates there is no upper limit.

func (*Validator) Required

func (v *Validator) Required(key string, value interface{}, message ...string)

Required validates that the value is not the type's zero value.

Currently supported types are string, int, int64, uint, uint64, bool, []string, and mail.Address. It will panic if the type is not supported.

func (*Validator) String

func (v *Validator) String() string

Strings representation of all errors, or a blank string if there are none.

func (*Validator) Sub

func (v *Validator) Sub(key, subKey string, err error)

Sub adds sub-validations.

Errors from the subvalidation are merged with the top-level one, the keys are added as "top.sub" or "top[n].sub".

If the error is not a Validator the text will be added as just the key name without subkey (i.e. the same as v.Append("key", "msg")).

For example:

func (c Customer) validateSettings() error {
    v := zvalidate.New()
    v.Required("domain", c.Domain)
    v.Required("email", c.Email)
    return v.ErrorOrNil()
}

v := zvalidate.New()
v.Required("name", customer.Name)

// Keys will be added as "settings.domain" and "settings.email".
v.Sub("settings", "", customer.validateSettings())

// List as array; keys will be added as "addresses[0].city" etc.
for i, addr := range customer.Addresses {
    v.Sub("addresses", i, addr.Validate())
}

func (*Validator) URL

func (v *Validator) URL(key, value string, message ...string) *url.URL

URL parses an URL.

The URL may consist of a scheme, host, path, and query parameters. Only the host is required.

Local URLs are not considered valid; the host needs to have at least two labels. Use URLLocal() if you also want to accept e.g "http://localhost".

If the scheme is not given "http" will be prepended.

func (*Validator) URLLocal

func (v *Validator) URLLocal(key, value string, message ...string) *url.URL

URLLocal is like URL, but also considers local URLs to be valid.

func (*Validator) UTF8

func (v *Validator) UTF8(key, value string, message ...string)

UTF8 validates that this string is valid UTF-8.

Caveat: this will consider NULL bytes *invalid* even though they're valid in UTF-8. Many tools don't accept it (e.g. PostgreSQL and SQLite), there's very rarely a reason to include them in strings, and most uses I've seen is from people trying to insert exploits. So the practical thing to do is just to reject it.

Version
v0.0.0-20211130163434-73d289f2a706 (latest)
Published
Nov 30, 2021
Platform
linux/amd64
Imports
15 packages (graph)
Last checked
2 months ago

Tools for package owners.