identifiers: adjust requirements for identifiers
Based on feedback, a few adjustments have been made to the identifier requirements. Identifiers that have components that start with a number are now allowed. This violates RFC 1035 but does not do so for dns names practically. A total length, of 76 characters is now also enforced. This decision was completely arbitrary but satifies the requirement for a maximum length. Often, this is used as the maximum length of a line in editors, so it should be a good choice. Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
		| @@ -6,8 +6,12 @@ | ||||
| // 2.3.1. This will make identifiers safe for use across networks, filesystems | ||||
| // and other media. | ||||
| // | ||||
| // While the character set may expand in the future, we guarantee that the | ||||
| // identifiers will be safe for use as filesystem path components. | ||||
| // The identifier specification departs from RFC 1035 in that it allows | ||||
| // "labels" to start with number and only enforces a total length restriction | ||||
| // of 76 characters. | ||||
| // | ||||
| // While the character set may be expanded in the future, identifiers are | ||||
| // guaranteed to be safely used as filesystem path components. | ||||
| package identifiers | ||||
|  | ||||
| import ( | ||||
| @@ -17,7 +21,9 @@ import ( | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	label = `[A-Za-z][A-Za-z0-9]+(?:[-]+[A-Za-z0-9]+)*` | ||||
| 	maxLength = 76 | ||||
| 	charclass = `[A-Za-z0-9]+` | ||||
| 	label     = charclass + `(:?[-]+` + charclass + `)*` | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -27,7 +33,7 @@ var ( | ||||
| 	// identifiers. | ||||
| 	identifierRe = regexp.MustCompile(reAnchor(label + reGroup("[.]"+reGroup(label)) + "*")) | ||||
|  | ||||
| 	errIdentifierInvalid = errors.Errorf("invalid, must match %v", identifierRe) | ||||
| 	errIdentifierInvalid = errors.New("invalid identifier") | ||||
| ) | ||||
|  | ||||
| // IsInvalid return true if the error was due to an invalid identifer. | ||||
| @@ -43,8 +49,12 @@ func IsInvalid(err error) bool { | ||||
| // In general, identifiers that pass this validation, should be safe for use as | ||||
| // a domain identifier or filesystem path component. | ||||
| func Validate(s string) error { | ||||
| 	if len(s) > maxLength { | ||||
| 		return errors.Wrapf(errIdentifierInvalid, "identifier %q greater than maximum length (%d characters)", s, maxLength) | ||||
| 	} | ||||
|  | ||||
| 	if !identifierRe.MatchString(s) { | ||||
| 		return errors.Wrapf(errIdentifierInvalid, "identifier %q", s) | ||||
| 		return errors.Wrapf(errIdentifierInvalid, "identifier %q must match %v", s, identifierRe) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package identifiers | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| @@ -15,6 +16,9 @@ func TestValidIdentifiers(t *testing.T) { | ||||
| 		"foo.boo", | ||||
| 		"swarmkit.docker.io", | ||||
| 		"zn--e9.org", // or something like it! | ||||
| 		"0912341234", | ||||
| 		"task.0.0123456789", | ||||
| 		strings.Repeat("a", maxLength), | ||||
| 	} { | ||||
| 		t.Run(input, func(t *testing.T) { | ||||
| 			if err := Validate(input); err != nil { | ||||
| @@ -34,6 +38,7 @@ func TestInvalidIdentifiers(t *testing.T) { | ||||
| 		"-foo.boo", | ||||
| 		"foo.boo-", | ||||
| 		"foo_foo.boo_underscores", // boo-urns? | ||||
| 		strings.Repeat("a", maxLength+1), | ||||
| 	} { | ||||
|  | ||||
| 		t.Run(input, func(t *testing.T) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Stephen J Day
					Stephen J Day