Skip to content

Commit 3ea9b93

Browse files
committed
Fix TLD validation to require fully alphabetic TLD per RFC 1123
RFC 1123 Section 2.1 states "the highest-level component label will be alphabetic". This updates validation to check that the entire TLD consists only of letters, not just that it starts with a letter.
1 parent 9da0a17 commit 3ea9b93

File tree

2 files changed

+13
-14
lines changed

2 files changed

+13
-14
lines changed

Sources/RFC 1123/RFC_1123.Domain.swift

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ extension RFC_1123.Domain: Hashable {
8989
}
9090
}
9191

92-
extension RFC_1123.Domain: UInt8.ASCII.RawRepresentable {}
92+
extension RFC_1123.Domain: Binary.ASCII.RawRepresentable {}
9393

9494
extension RFC_1123.Domain: CustomStringConvertible {}
9595

96-
extension RFC_1123.Domain: UInt8.ASCII.Serializable {
96+
extension RFC_1123.Domain: Binary.ASCII.Serializable {
9797
public static func serialize<Buffer: RangeReplaceableCollection>(
9898
ascii domain: Self,
9999
into buffer: inout Buffer
@@ -185,11 +185,10 @@ extension RFC_1123.Domain: UInt8.ASCII.Serializable {
185185
}
186186
}
187187

188-
// RFC 1123 hostname-level constraint:
189-
// "at least the highest-level component label will be alphabetic"
188+
// RFC 1123 Section 2.1:
189+
// "the highest-level component label will be alphabetic"
190190
if let tld = labels.last {
191-
let firstByte = tld.rawValue.utf8.first!
192-
guard firstByte.ascii.isLetter else {
191+
guard tld.rawValue.utf8.allSatisfy({ $0.ascii.isLetter }) else {
193192
throw Error.invalidTLD(tld.rawValue)
194193
}
195194
}
@@ -287,10 +286,10 @@ extension RFC_1123.Domain {
287286
throw Error.tooLong(name.count)
288287
}
289288

290-
// Validate TLD constraint
289+
// RFC 1123 Section 2.1:
290+
// "the highest-level component label will be alphabetic"
291291
if let tld = labels.last {
292-
let firstByte = tld.rawValue.utf8.first!
293-
guard firstByte.ascii.isLetter else {
292+
guard tld.rawValue.utf8.allSatisfy({ $0.ascii.isLetter }) else {
294293
throw Error.invalidTLD(tld.rawValue)
295294
}
296295
}

Tests/RFC 1123 Tests/RFC 1123 Tests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ struct `RFC 1123 Host Tests` {
4343
}
4444

4545
@Test
46-
func `Successfully creates host with TLD ending with number`() throws {
47-
// RFC 1123 only requires TLD to START with a letter, not end with one
48-
let host = try RFC_1123.Domain("example.com123")
49-
#expect(host.name == "example.com123")
50-
#expect(host.tld?.rawValue == "com123")
46+
func `Fails with invalid TLD ending with number`() throws {
47+
// RFC 1123 Section 2.1: "the highest-level component label will be alphabetic"
48+
#expect(throws: RFC_1123.Domain.Error.invalidTLD("com123")) {
49+
_ = try RFC_1123.Domain("example.com123")
50+
}
5151
}
5252

5353
@Test

0 commit comments

Comments
 (0)