Repository: go-playground/validator
Pull request #833 (2021-09-16 03:22:55)

Add DNS RFC 1035 label format validator
## Enhances

**Make sure that you've checked the boxes below before you submit PR:**
- [x] Tests exist or have been written that cover this particular change.

Change details:

- Add DNS RFC 1035 label validation based on [RFC 1035](https://datatracker.ietf.org/doc/html/rfc1035)

@go-playground/validator-maintainers

coveralls: 
[![Coverage Status](https://coveralls.io/builds/42911538/badge)](https://coveralls.io/builds/42911538)

Coverage increased (+0.01%) to 75.11% when pulling **e522ad3eb523f4f892aaf2d6ba115f5b28c59a43 on 0n1shi:dns_rfc1035** into **ce34f361cca51e25715399ab801c5e1c01d02d89 on go-playground:master**.


Patch:
diff --git a/baked_in.go b/baked_in.go
index 51a224c..d80ec48 100644
--- a/baked_in.go
+++ b/baked_in.go
@@ -198,6 +198,7 @@ var (
 		"postcode_iso3166_alpha2":       isPostcodeByIso3166Alpha2,
 		"postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
 		"bic":                           isIsoBicFormat,
+		"dns_rfc1035_label":             isDnsRFC1035LabelFormat,
 	}
 )
 
@@ -2413,3 +2414,11 @@ func isIsoBicFormat(fl FieldLevel) bool {
 
 	return bicRegex.MatchString(bicString)
 }
+
+// isDnsRFC1035LabelFormat is the validation function
+// for validating if the current field's value is
+// a valid dns RFC 1035 label, defined in RFC 1035.
+func isDnsRFC1035LabelFormat(fl FieldLevel) bool {
+	val := fl.Field().String()
+	return dnsRegexRFC1035Label.MatchString(val)
+}
diff --git a/doc.go b/doc.go
index 8c25847..a5d394a 100644
--- a/doc.go
+++ b/doc.go
@@ -1255,6 +1255,13 @@ More information on https://www.iso.org/standard/60390.html
 
 	Usage: bic
 
+RFC 1035 label
+
+This validates that a string value is a valid dns RFC 1035 label, defined in RFC 1035.
+More information on https://datatracker.ietf.org/doc/html/rfc1035
+
+	Usage: dns_rfc1035_label
+
 TimeZone
 
 This validates that a string value is a valid time zone based on the time zone database present on the system.
diff --git a/regexes.go b/regexes.go
index bac3a55..19e7c29 100644
--- a/regexes.go
+++ b/regexes.go
@@ -51,6 +51,7 @@ const (
 	jWTRegexString                   = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$"
 	splitParamsRegexString           = `'[^']*'|\S+`
 	bicRegexString                   = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$`
+	dnsRegexStringRFC1035Label       = "^[a-z]([-a-z0-9]*[a-z0-9]){0,62}$"
 )
 
 var (
@@ -102,4 +103,5 @@ var (
 	jWTRegex                   = regexp.MustCompile(jWTRegexString)
 	splitParamsRegex           = regexp.MustCompile(splitParamsRegexString)
 	bicRegex                   = regexp.MustCompile(bicRegexString)
+	dnsRegexRFC1035Label       = regexp.MustCompile(dnsRegexStringRFC1035Label)
 )


Test patch:
diff --git a/validator_test.go b/validator_test.go
index 5064139..799efdf 100644
--- a/validator_test.go
+++ b/validator_test.go
@@ -11343,6 +11343,45 @@ func TestBicIsoFormatValidation(t *testing.T) {
 	}
 }
 
+func TestRFC1035LabelFormatValidation(t *testing.T) {
+	tests := []struct {
+		value    string `validate:"dns_rfc1035_label"`
+		tag      string
+		expected bool
+	}{
+		{"abc", "dns_rfc1035_label", true},
+		{"abc-", "dns_rfc1035_label", false},
+		{"abc-123", "dns_rfc1035_label", true},
+		{"ABC", "dns_rfc1035_label", false},
+		{"ABC-123", "dns_rfc1035_label", false},
+		{"abc-abc", "dns_rfc1035_label", true},
+		{"ABC-ABC", "dns_rfc1035_label", false},
+		{"123-abc", "dns_rfc1035_label", false},
+		{"", "dns_rfc1035_label", false},
+	}
+
+	validate := New()
+
+	for i, test := range tests {
+		errs := validate.Var(test.value, test.tag)
+
+		if test.expected {
+			if !IsEqual(errs, nil) {
+				t.Fatalf("Index: %d dns_rfc1035_label failed Error: %s", i, errs)
+			}
+		} else {
+			if IsEqual(errs, nil) {
+				t.Fatalf("Index: %d dns_rfc1035_label failed Error: %s", i, errs)
+			} else {
+				val := getError(errs, "", "")
+				if val.Tag() != "dns_rfc1035_label" {
+					t.Fatalf("Index: %d dns_rfc1035_label failed Error: %s", i, errs)
+				}
+			}
+		}
+	}
+}
+
 func TestPostCodeByIso3166Alpha2(t *testing.T) {
 	tests := map[string][]struct {
 		value    string