Skip to content

Commit 0879634

Browse files
committed
Append new validations
- hostname - fqdn
1 parent 44d9acf commit 0879634

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

baked_in.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ var (
125125
"ip_addr": isIPAddrResolvable,
126126
"unix_addr": isUnixAddrResolvable,
127127
"mac": isMAC,
128+
"hostname": isHostname,
129+
"fqdn": isFQDN,
128130
}
129131
)
130132

@@ -1477,3 +1479,18 @@ func isIP6Addr(fl FieldLevel) bool {
14771479

14781480
return ip != nil && ip.To4() == nil
14791481
}
1482+
1483+
func isHostname(fl FieldLevel) bool {
1484+
return hostnameRegex.MatchString(fl.Field().String())
1485+
}
1486+
1487+
func isFQDN(fl FieldLevel) bool {
1488+
val := fl.Field().String()
1489+
1490+
if val[len(val)-1] == '.' && val[len(val)-2] != '.' {
1491+
val = strings.TrimRight(val, ".")
1492+
}
1493+
1494+
return hostnameRegex.MatchString(val) &&
1495+
(strings.IndexAny(val, ".") > -1)
1496+
}

doc.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,18 @@ Note: See Go's ParseMAC for accepted formats and types:
794794
795795
http://golang.org/src/net/mac.go?s=866:918#L29
796796
797+
Hostname
798+
799+
This validates that a stringa value is a valid Hostname
800+
801+
Usage: hostname
802+
803+
Full Qualified Domain Name (FQDN)
804+
805+
This validates that a string value contains a valid FQDN.
806+
807+
Usage: fqdn
808+
797809
Alias Validators and Tags
798810
799811
NOTE: When returning an error, the tag returned in "FieldError" will be

regexes.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const (
3030
latitudeRegexString = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
3131
longitudeRegexString = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
3232
sSNRegexString = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
33+
hostnameRegexString = `^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$`
3334
)
3435

3536
var (
@@ -60,4 +61,5 @@ var (
6061
latitudeRegex = regexp.MustCompile(latitudeRegexString)
6162
longitudeRegex = regexp.MustCompile(longitudeRegexString)
6263
sSNRegex = regexp.MustCompile(sSNRegexString)
64+
hostnameRegex = regexp.MustCompile(hostnameRegexString)
6365
)

validator_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7119,3 +7119,96 @@ func TestValidateStructRegisterCtx(t *testing.T) {
71197119
Equal(t, ctxVal, "testval")
71207120
Equal(t, ctxSlVal, "slVal")
71217121
}
7122+
7123+
func TestHostnameValidation(t *testing.T) {
7124+
tests := []struct {
7125+
param string
7126+
expected bool
7127+
}{
7128+
{"test.example.com", true},
7129+
{"example.com", true},
7130+
{"example24.com", true},
7131+
{"test.example24.com", true},
7132+
{"test24.example24.com", true},
7133+
{"example", true},
7134+
{"test.example.com.", false},
7135+
{"example.com.", false},
7136+
{"example24.com.", false},
7137+
{"test.example24.com.", false},
7138+
{"test24.example24.com.", false},
7139+
{"example.", false},
7140+
{"192.168.0.1", false},
7141+
{"[email protected]", false},
7142+
{"2001:cdba:0000:0000:0000:0000:3257:9652", false},
7143+
{"2001:cdba:0:0:0:0:3257:9652", false},
7144+
{"2001:cdba::3257:9652", false},
7145+
}
7146+
7147+
validate := New()
7148+
7149+
for i, test := range tests {
7150+
7151+
errs := validate.Var(test.param, "hostname")
7152+
7153+
if test.expected {
7154+
if !IsEqual(errs, nil) {
7155+
t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
7156+
}
7157+
} else {
7158+
if IsEqual(errs, nil) {
7159+
t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
7160+
} else {
7161+
val := getError(errs, "", "")
7162+
if val.Tag() != "hostname" {
7163+
t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
7164+
}
7165+
}
7166+
}
7167+
}
7168+
}
7169+
7170+
func TestFQDNValidation(t *testing.T) {
7171+
tests := []struct {
7172+
param string
7173+
expected bool
7174+
}{
7175+
{"test.example.com", true},
7176+
{"example.com", true},
7177+
{"example24.com", true},
7178+
{"test.example24.com", true},
7179+
{"test24.example24.com", true},
7180+
{"test.example.com.", true},
7181+
{"example.com.", true},
7182+
{"example24.com.", true},
7183+
{"test.example24.com.", true},
7184+
{"test24.example24.com.", true},
7185+
{"example", false},
7186+
{"192.168.0.1", false},
7187+
{"[email protected]", false},
7188+
{"2001:cdba:0000:0000:0000:0000:3257:9652", false},
7189+
{"2001:cdba:0:0:0:0:3257:9652", false},
7190+
{"2001:cdba::3257:9652", false},
7191+
}
7192+
7193+
validate := New()
7194+
7195+
for i, test := range tests {
7196+
7197+
errs := validate.Var(test.param, "fqdn")
7198+
7199+
if test.expected {
7200+
if !IsEqual(errs, nil) {
7201+
t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
7202+
}
7203+
} else {
7204+
if IsEqual(errs, nil) {
7205+
t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
7206+
} else {
7207+
val := getError(errs, "", "")
7208+
if val.Tag() != "fqdn" {
7209+
t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
7210+
}
7211+
}
7212+
}
7213+
}
7214+
}

0 commit comments

Comments
 (0)