Skip to content

Commit

Permalink
workaround Foundation.URL behavior changes (#777)
Browse files Browse the repository at this point in the history
`Foundation.URL` has various behavior changes in Swift 6 to better match
RFC 3986 which impact AHC.

In particular it now no longer strips the square brackets in IPv6 hosts
which are not tolerated by `inet_pton` so these must be manually
stripped.

swiftlang/swift-foundation#957
swiftlang/swift-foundation#958
swiftlang/swift-foundation#962
  • Loading branch information
rnro authored Oct 3, 2024
1 parent 64abc77 commit 0a9b723
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension HTTPClientRequest {
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension HTTPClientRequest.Prepared {
init(_ request: HTTPClientRequest, dnsOverride: [String: String] = [:]) throws {
guard let url = URL(string: request.url) else {
guard !request.url.isEmpty, let url = URL(string: request.url) else {
throw HTTPClientError.invalidURL
}

Expand Down
30 changes: 30 additions & 0 deletions Sources/AsyncHTTPClient/DeconstructedURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,16 @@ extension DeconstructedURL {

switch scheme {
case .http, .https:
#if !canImport(Darwin) && compiler(>=6.0)
guard let urlHost = url.host, !urlHost.isEmpty else {
throw HTTPClientError.emptyHost
}
let host = urlHost.trimIPv6Brackets()
#else
guard let host = url.host, !host.isEmpty else {
throw HTTPClientError.emptyHost
}
#endif
self.init(
scheme: scheme,
connectionTarget: .init(remoteHost: host, port: url.port ?? scheme.defaultPort),
Expand Down Expand Up @@ -81,3 +88,26 @@ extension DeconstructedURL {
}
}
}

#if !canImport(Darwin) && compiler(>=6.0)
extension String {
@inlinable internal func trimIPv6Brackets() -> String {
var utf8View = self.utf8[...]

var modified = false
if utf8View.first == UInt8(ascii: "[") {
utf8View = utf8View.dropFirst()
modified = true
}
if utf8View.last == UInt8(ascii: "]") {
utf8View = utf8View.dropLast()
modified = true
}

if modified {
return String(Substring(utf8View))
}
return self
}
}
#endif
6 changes: 5 additions & 1 deletion Tests/AsyncHTTPClientTests/HTTPClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ final class HTTPClientTests: XCTestCaseHTTPClientTestsBaseClass {
XCTAssertEqual(request2.url.path, "")

let request3 = try Request(url: "unix:///tmp/file")
XCTAssertNil(request3.url.host)
XCTAssertEqual(request3.host, "")
#if os(Linux) && compiler(>=6.0)
XCTAssertEqual(request3.url.host, "")
#else
XCTAssertNil(request3.url.host)
#endif
XCTAssertEqual(request3.url.path, "/tmp/file")
XCTAssertEqual(request3.port, 80)
XCTAssertFalse(request3.useTLS)
Expand Down

0 comments on commit 0a9b723

Please sign in to comment.