Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: URN RFC 8141 #1224

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions baked_in.go
Expand Up @@ -130,6 +130,7 @@ var (
"url": isURL,
"http_url": isHttpURL,
"uri": isURI,
"urn": isUrnRFC8141, // RFC 8141
"urn_rfc2141": isUrnRFC2141, // RFC 2141
"file": isFile,
"filepath": isFilePath,
Expand Down Expand Up @@ -1505,6 +1506,23 @@ func isHttpURL(fl FieldLevel) bool {
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}

// isUrnRFC8141 is the validation function for validating if the current field's value is a valid URN as per RFC 8141.
func isUrnRFC8141(fl FieldLevel) bool {
field := fl.Field()

switch field.Kind() {
case reflect.String:

str := field.String()

_, match := urn.Parse([]byte(str), urn.WithParsingMode(urn.RFC8141Only))

return match
}

panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}

// isUrnRFC2141 is the validation function for validating if the current field's value is a valid URN as per RFC 2141.
func isUrnRFC2141(fl FieldLevel) bool {
field := fl.Field()
Expand Down
7 changes: 7 additions & 0 deletions doc.go
Expand Up @@ -909,6 +909,13 @@ This will accept any uri the golang request uri accepts

Usage: uri

# Urn RFC 8141 String

This validataes that a string value contains a valid URN
according to the RFC 8141 spec.

Usage: urn

# Urn RFC 2141 String

This validataes that a string value contains a valid URN
Expand Down
77 changes: 77 additions & 0 deletions validator_test.go
Expand Up @@ -8134,6 +8134,83 @@ func TestUrnRFC2141(t *testing.T) {
PanicMatches(t, func() { _ = validate.Var(i, tag) }, "Bad field type int")
}

func TestUrnRFC8141(t *testing.T) {
tests := []struct {
param string
expected bool
}{
{"urn:lex:it:ministero.giustizia:decreto:1992-07-24;358~art5", true},
{"urn:nid:nss/", true},
{"urn:nid:nss&", true},
{"urn:example:1/406/47452/2", true},
{"urn:example:foo-bar-baz-qux?+CCResolve:cc=uk", true},
{"urn:example:foo-bar-baz-qux?+&", true},
{"urn:example:foo-bar-baz-qux?+%16CCResolve:cc=uk", true},
{"urn:example:weather?=op=map&lat=39.56&lon=-104.85&datetime=1969-07-21T02:56:15Z", true},
{"urn:example:CamelCase1/406/47452/2?=lat=41.22255&long=16.06596#frag?some/slash/~%D0", true},
{"urn:example:CamelCase1/406/47452/2?=lat=41.22255&long=16.06596#frag", true},
{"URN:signs:()+,-.:=@;$_!*alnum123456789", true},
{"URN:abcd-abcd:x", true},
{"urn:urnx:urn", true},
{"urn:ciao:a:b:c", true},
{"urn:aaa:x:y:", true},
{"urn:ciao:-", true},
{"urn:colon:::::nss", true},
{"urn:ciao:@!=%2C(xyz)+a,b.*@g=$_'", true},
{"URN:hexes:%25", true},
{"URN:xyz:abc%1Dz%2F%3az", true},
{"URN:foo:a123,456", true},
{"urn:foo:a123,456", true},
{"urn:FOO:a123,456", true},
{"urn:foo:A123,456", true},
{"urn:foo:a123%2C456", true},
{"URN:FOO:a123%2c456", true},
{"URN:FOO:ABC%FFabc123%2c456", true},
{"URN:FOO:ABC%FFabc123%2C456%9A", true},
{"urn:ietf:params:scim:schemas:core:2.0:User", true},
{"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:meta.lastModified", true},
{"urn:urn-7:informal", true},
{"urn:aa:", false},
{"URN:x:abc%1Dz%2F%3az", false},
{"urn:123456789-1234567890-abcdefghilmn:o", false},
{"urn:ex:ex?+a?+", false},
{"urn:xn--:nss", false},
{"urn:a:nss", false},
{"URN:trailing-:w", false},
{"URN:-leading:w", false},
{"urn:urn-s:nss", false},
{"urn:urn-0:nss", false},
{"urn:", false},
}

tag := "urn"

validate := New()

for i, test := range tests {

errs := validate.Var(test.param, tag)

if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d URN failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d URN failed Error: %s", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != tag {
t.Fatalf("Index: %d URN failed Error: %s", i, errs)
}
}
}
}

i := 1
PanicMatches(t, func() { _ = validate.Var(i, tag) }, "Bad field type int")
}

func TestUrl(t *testing.T) {
tests := []struct {
param string
Expand Down