diff --git a/Sources/FoundationEssentials/URL/URLParser.swift b/Sources/FoundationEssentials/URL/URLParser.swift index efea6b538..7ea11362c 100644 --- a/Sources/FoundationEssentials/URL/URLParser.swift +++ b/Sources/FoundationEssentials/URL/URLParser.swift @@ -222,6 +222,8 @@ internal struct RFC3986Parser: URLParserProtocol { "addressbook", "contact", "phasset", + "http+unix", + "https+unix", ]) private static func looksLikeIPLiteral(_ host: some StringProtocol) -> Bool { diff --git a/Tests/FoundationEssentialsTests/URLTests.swift b/Tests/FoundationEssentialsTests/URLTests.swift index a1f7c6b49..4d15ee0c0 100644 --- a/Tests/FoundationEssentialsTests/URLTests.swift +++ b/Tests/FoundationEssentialsTests/URLTests.swift @@ -1031,4 +1031,38 @@ final class URLTests : XCTestCase { XCTAssertEqual(comp.percentEncodedPath, "/my%00path") XCTAssertEqual(comp.path, "/my\u{0}path") } + + func testURLComponentsUnixDomainSocketOverHTTPScheme() { + var comp = URLComponents() + comp.scheme = "http+unix" + comp.host = "/path/to/socket" + comp.path = "/info" + XCTAssertEqual(comp.string, "http+unix://%2Fpath%2Fto%2Fsocket/info") + + comp.scheme = "https+unix" + XCTAssertEqual(comp.string, "https+unix://%2Fpath%2Fto%2Fsocket/info") + + comp.encodedHost = "%2Fpath%2Fto%2Fsocket" + XCTAssertEqual(comp.string, "https+unix://%2Fpath%2Fto%2Fsocket/info") + XCTAssertEqual(comp.encodedHost, "%2Fpath%2Fto%2Fsocket") + XCTAssertEqual(comp.host, "/path/to/socket") + XCTAssertEqual(comp.path, "/info") + + // "/path/to/socket" is not a valid host for schemes + // that IDNA-encode hosts instead of percent-encoding + comp.scheme = "http" + XCTAssertNil(comp.string) + + comp.scheme = "https" + XCTAssertNil(comp.string) + + comp.scheme = "https+unix" + XCTAssertEqual(comp.string, "https+unix://%2Fpath%2Fto%2Fsocket/info") + + // Check that we can parse a percent-encoded http+unix URL string + comp = URLComponents(string: "http+unix://%2Fpath%2Fto%2Fsocket/info")! + XCTAssertEqual(comp.encodedHost, "%2Fpath%2Fto%2Fsocket") + XCTAssertEqual(comp.host, "/path/to/socket") + XCTAssertEqual(comp.path, "/info") + } }