is/web.go   A
last analyzed

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 43
dl 0
loc 110
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A is.IPv4 0 2 1
A is.IPv6 0 2 1
A is.StrictHostname 0 18 5
A is.Hostname 0 2 2
A is.HTML5Email 0 2 1
A is.IP 0 2 1
A is.Email 0 2 1
A is.URL 0 2 1
1
package is
2
3
import (
4
	"net"
5
	"net/url"
6
	"regexp"
7
	"strings"
8
9
	"github.com/muonsoft/validation/validate"
10
)
11
12
// Email is used for simplified validation of an email address. It allows all values
13
// with an "@" symbol in, and a "." in the second host part of the email address.
14
func Email(value string) bool {
15
	return looseEmailRegex.MatchString(value)
16
}
17
18
// HTML5Email is used for validation of an email address based on pattern for HTML5
19
// (see https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address).
20
func HTML5Email(value string) bool {
21
	return html5EmailRegex.MatchString(value)
22
}
23
24
// URL is used to validate that value is a valid URL string. You can use a list of restrictions
25
// to additionally check for a restricted set of URLs. By default, if no restrictions are passed,
26
// the function checks for the http:// and https:// schemas.
27
//
28
// Use the callable option to configure the list of expected schemas. If an empty string
29
// is passed as a schema, then URL value may be treated as relative (without schema, e.g. "//example.com").
30
//
31
// Use the [github.com/muonsoft/validation/validate.RestrictURLHosts] or
32
// [github.com/muonsoft/validation/validate.RestrictURLHostByPattern] option to configure
33
// the list of allowed hosts.
34
func URL(value string, restrictions ...func(u *url.URL) error) bool {
35
	return validate.URL(value, restrictions...) == nil
36
}
37
38
// IP checks that a value is a valid IP address (IPv4 or IPv6). You can use a list
39
// of restrictions to additionally check for a restricted range of IPs.
40
func IP(value string, restrictions ...func(ip net.IP) error) bool {
41
	return validate.IP(value, restrictions...) == nil
42
}
43
44
// IPv4 checks that a value is a valid IPv4 address. You can use a list
45
// of restrictions to additionally check for a restricted range of IPs.
46
func IPv4(value string, restrictions ...func(ip net.IP) error) bool {
47
	return validate.IPv4(value, restrictions...) == nil
48
}
49
50
// IPv6 checks that a value is a valid IPv6 address. You can use a list
51
// of restrictions to additionally check for a restricted range of IPs.
52
func IPv6(value string, restrictions ...func(ip net.IP) error) bool {
53
	return validate.IPv6(value, restrictions...) == nil
54
}
55
56
// Hostname checks that a value is a valid hostname. It checks that each label
57
// within a valid hostname may be no more than 63 octets long. Also, it checks that
58
// the total length of the hostname must not exceed 255 characters.
59
//
60
// See [StrictHostname] for additional checks.
61
func Hostname(value string) bool {
62
	return hostnameRegex.MatchString(value) && len(strings.ReplaceAll(value, ".", "")) <= 255
63
}
64
65
// StrictHostname checks that a value is a valid hostname. Beside checks from Hostname function
66
// it checks that hostname is fully qualified and include its top-level domain name (TLD).
67
// For instance, example.com is valid but example is not.
68
//
69
// Additionally it checks for reserved top-level domains according to RFC 2606 and
70
// that's why hostnames containing them are not considered valid:
71
// .example, .invalid, .localhost, and .test.
72
func StrictHostname(value string) bool {
73
	if !Hostname(value) {
74
		return false
75
	}
76
77
	domains := strings.Split(value, ".")
78
	if len(domains) < 2 {
79
		return false
80
	}
81
82
	tld := domains[len(domains)-1]
83
	for _, reservedTLD := range reservedTopLevelDomains {
84
		if tld == reservedTLD {
85
			return false
86
		}
87
	}
88
89
	return true
90
}
91
92
var reservedTopLevelDomains = []string{
93
	"example",
94
	"invalid",
95
	"localhost",
96
	"test",
97
}
98
99
const (
100
	looseEmailPattern = `^.+\@\S+\.\S+$`
101
	html5EmailPattern = "^[a-zA-Z0-9.!#$%&\\'*+\\\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$"
102
103
	// source https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
104
	hostnamePattern = `^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`
105
)
106
107
var (
108
	looseEmailRegex = regexp.MustCompile(looseEmailPattern)
109
	html5EmailRegex = regexp.MustCompile(html5EmailPattern)
110
	hostnameRegex   = regexp.MustCompile(hostnamePattern)
111
)
112