diff --git a/urns/parser.go b/urns/parser.go index 51848fd..1350974 100644 --- a/urns/parser.go +++ b/urns/parser.go @@ -7,13 +7,6 @@ import ( // Simple URN parser loosely based on RFC2141 (https://www.ietf.org/rfc/rfc2141.txt) -const ( - stateScheme = iota - statePath - stateQuery - stateFragment -) - var escapes = map[rune]string{ '#': `%23`, '%': `%25`, @@ -39,6 +32,13 @@ func (u *parsedURN) String() string { return s } +const ( + stateScheme = iota + statePath + stateQuery + stateFragment +) + func parseURN(urn string) (*parsedURN, error) { state := stateScheme @@ -74,8 +74,11 @@ func parseURN(urn string) (*parsedURN, error) { buffers[state].WriteRune(c) } - if state == stateScheme || buffers[stateScheme].Len() == 0 { - return nil, fmt.Errorf("must contain at least scheme and path") + if buffers[stateScheme].Len() == 0 { + return nil, fmt.Errorf("scheme cannot be empty") + } + if buffers[statePath].Len() == 0 { + return nil, fmt.Errorf("path cannot be empty") } return &parsedURN{ diff --git a/urns/parser_test.go b/urns/parser_test.go index 8f696ad..fb1957c 100644 --- a/urns/parser_test.go +++ b/urns/parser_test.go @@ -29,8 +29,9 @@ func TestParseURNAndBack(t *testing.T) { // can't single part {input: "xyz", hasError: true}, - // can't omit scheme + // can't omit scheme or path {input: ":path", hasError: true}, + {input: "scheme:", hasError: true}, // can't have multiple queries or fragments {input: "scheme:path?query?query", hasError: true}, diff --git a/urns/urns.go b/urns/urns.go index 697d9ec..2bf824d 100644 --- a/urns/urns.go +++ b/urns/urns.go @@ -175,14 +175,14 @@ func (u URN) Normalize(country string) URN { // Validate returns whether this URN is considered valid func (u URN) Validate() error { scheme, path, _, display := u.ToParts() + + if scheme == "" || path == "" { + return fmt.Errorf("scheme or path cannot be empty") + } if !IsValidScheme(scheme) { return fmt.Errorf("invalid scheme: '%s'", scheme) } - if path == "" { - return fmt.Errorf("path cannot be empty") - } - switch scheme { case TelScheme: // validate is possible phone number diff --git a/urns/urns_test.go b/urns/urns_test.go index c765d5a..b5d7285 100644 --- a/urns/urns_test.go +++ b/urns/urns_test.go @@ -233,9 +233,9 @@ func TestValidate(t *testing.T) { urn URN expectedError string }{ - {"xxxx", "invalid scheme"}, // un-parseable URNs don't validate - {"xyz:abc", "invalid scheme"}, // nor do unknown schemes - {"tel:", "path cannot be empty"}, + {"xxxx", "scheme or path cannot be empty"}, // un-parseable URNs don't validate + {"xyz:abc", "invalid scheme"}, // nor do unknown schemes + {"tel:", "scheme or path cannot be empty"}, // valid tel numbers {"tel:+250788383383", ""}, @@ -301,7 +301,7 @@ func TestValidate(t *testing.T) { } if err != nil && !strings.Contains(err.Error(), tc.expectedError) { - t.Errorf("Failed wrong error, '%s' not found in '%s'", tc.expectedError, err.Error()) + t.Errorf("Failed wrong error, '%s' not found in '%s' for '%s'", tc.expectedError, err.Error(), string(tc.urn)) } }