Skip to content

Commit cdf57cb

Browse files
Added support for the new http+unix and https+unix schemes
Motivation: We can now not only make connections over sockets using the existing unix: baseURL approach, but also by %-escaping the socket path as the URL's hostname, and using the http+unix: or https+unix: schemes for plain HTTP or HTTP over TLS support. Modifications: Added references to the new url schemes where necessary, aand added a missingSocketPath error for when the socket path is not encoded as the hostname. Result: The tests now pass, and connections can be made over non-special URLs, supporting TLS if necessary.
1 parent 3e409d4 commit cdf57cb

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

Sources/AsyncHTTPClient/ConnectionPool.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ final class ConnectionPool {
113113
self.scheme = .https
114114
case "unix":
115115
self.scheme = .unix
116+
case "http+unix":
117+
self.scheme = .http_unix
118+
case "https+unix":
119+
self.scheme = .https_unix
116120
default:
117121
fatalError("HTTPClient.Request scheme should already be a valid one")
118122
}
@@ -130,10 +134,12 @@ final class ConnectionPool {
130134
case http
131135
case https
132136
case unix
137+
case http_unix
138+
case https_unix
133139

134140
var requiresTLS: Bool {
135141
switch self {
136-
case .https:
142+
case .https, .https_unix:
137143
return true
138144
default:
139145
return false
@@ -455,7 +461,7 @@ class HTTP1ConnectionProvider {
455461
case .http, .https:
456462
let address = HTTPClient.resolveAddress(host: self.key.host, port: self.key.port, proxy: self.configuration.proxy)
457463
channel = bootstrap.connect(host: address.host, port: address.port)
458-
case .unix:
464+
case .unix, .http_unix, .https_unix:
459465
channel = bootstrap.connect(unixDomainSocketPath: self.key.unixPath)
460466
}
461467

Sources/AsyncHTTPClient/HTTPClient.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ public struct HTTPClientError: Error, Equatable, CustomStringConvertible {
726726
private enum Code: Equatable {
727727
case invalidURL
728728
case emptyHost
729+
case missingSocketPath
729730
case alreadyShutdown
730731
case emptyScheme
731732
case unsupportedScheme(String)
@@ -758,6 +759,8 @@ public struct HTTPClientError: Error, Equatable, CustomStringConvertible {
758759
public static let invalidURL = HTTPClientError(code: .invalidURL)
759760
/// URL does not contain host.
760761
public static let emptyHost = HTTPClientError(code: .emptyHost)
762+
/// URL does not contain a socketPath as a host for http(s)+unix shemes.
763+
public static let missingSocketPath = HTTPClientError(code: .missingSocketPath)
761764
/// Client is shutdown and cannot be used for new requests.
762765
public static let alreadyShutdown = HTTPClientError(code: .alreadyShutdown)
763766
/// URL does not contain scheme.

Sources/AsyncHTTPClient/HTTPHandler.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ extension HTTPClient {
101101
enum Kind {
102102
enum UnixScheme {
103103
case baseURL
104+
case http_unix
105+
case https_unix
104106
}
105107

106108
/// Remote host request.
@@ -109,14 +111,16 @@ extension HTTPClient {
109111
case unixSocket(_ scheme: UnixScheme)
110112

111113
private static var hostSchemes = ["http", "https"]
112-
private static var unixSchemes = ["unix"]
114+
private static var unixSchemes = ["unix", "http+unix", "https+unix"]
113115

114116
init(forScheme scheme: String) throws {
115117
if Kind.host.supports(scheme: scheme) {
116118
self = .host
117119
} else if Kind.unixSchemes.contains(scheme) {
118120
switch scheme {
119121
case "unix": self = .unixSocket(.baseURL)
122+
case "http+unix": self = .unixSocket(.http_unix)
123+
case "https+unix": self = .unixSocket(.https_unix)
120124
default: preconditionFailure("scheme should already be a valid option")
121125
}
122126
} else {
@@ -142,6 +146,11 @@ extension HTTPClient {
142146
switch scheme {
143147
case .baseURL:
144148
return url.baseURL?.path ?? url.path
149+
case .http_unix, .https_unix:
150+
guard let socketPath = url.host else {
151+
throw HTTPClientError.missingSocketPath
152+
}
153+
return socketPath
145154
}
146155
case .host:
147156
return ""
@@ -156,6 +165,8 @@ extension HTTPClient {
156165
switch scheme {
157166
case .baseURL:
158167
return url.baseURL != nil ? url.uri : "/"
168+
case .http_unix, .https_unix:
169+
return url.uri
159170
}
160171
}
161172
}
@@ -227,6 +238,7 @@ extension HTTPClient {
227238
/// - `emptyScheme` if URL does not contain HTTP scheme.
228239
/// - `unsupportedScheme` if URL does contains unsupported HTTP scheme.
229240
/// - `emptyHost` if URL does not contains a host.
241+
/// - `missingSocketPath` if URL does not contains a socketPath as an encoded host.
230242
public init(url: URL, method: HTTPMethod = .GET, headers: HTTPHeaders = HTTPHeaders(), body: Body? = nil) throws {
231243
guard let scheme = url.scheme?.lowercased() else {
232244
throw HTTPClientError.emptyScheme
@@ -247,7 +259,7 @@ extension HTTPClient {
247259

248260
/// Whether request will be executed using secure socket.
249261
public var useTLS: Bool {
250-
return self.scheme == "https"
262+
return self.scheme == "https" || self.scheme == "https+unix"
251263
}
252264

253265
/// Resolved port.

0 commit comments

Comments
 (0)