Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| http_url | HTTP URL String |
| url_encoded | URL Encoded |
| urn_rfc2141 | Urn RFC 2141 String |
| urn_rfc8141 | Urn RFC 8141 String |

### Strings:

Expand Down
18 changes: 18 additions & 0 deletions baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ var (
"url": isURL,
"http_url": isHttpURL,
"uri": isURI,
"urn_rfc8141": 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()
Comment thread
leodido marked this conversation as resolved.

_, 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
Original file line number Diff line number Diff line change
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_rfc8141

# 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
Original file line number Diff line number Diff line change
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_rfc8141"

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