Add unix domain socket support for bind targets - #96
mob-connection wants to merge 12 commits into
Conversation
| /// ```swift | ||
| /// let target = BindTarget.unixDomainSocket(path: "/tmp/server.sock") | ||
| /// ``` | ||
| public static func unixDomainSocket(path: String) -> Self { |
There was a problem hiding this comment.
This should probably use the new FilePath type once it becomes available
There was a problem hiding this comment.
This should probably use the new
FilePathtype once it becomes available
In the UDS bind support the socket path has two different types depending on direction: on input we take a FilePath (BindTarget.unixDomainSocket(path:)), but on output we expose it as String (SocketAddress.unixDomainSocketPath, mirroring NIOCore.SocketAddress.pathname). If we commit to FilePath, I'd lean toward using it on output too for consistency — but keeping String also makes sense since that's just what NIO reports back. Which way should we go?
There was a problem hiding this comment.
Yeah I think ignore what NIO does and keep the API what looks the best in Swift, in this case FilePaths for all types that represent instead of a String
Adds a `.unixDomainSocket(path:)` bind target so the server can listen on a UNIX domain socket in addition to host and port. - Add `BindTarget.unixDomainSocket(path:)` and a matching `SocketAddress` case - Bind via `ServerBootstrap.bind(unixDomainSocketPath:)` for both plaintext and secure-upgrade channels, and report the bound path from `listeningAddresses` - Remove the socket file on shutdown; fail the bind if the path is already occupied so a stale socket is never silently reused - Support a `socketPath` key in swift-configuration, mutually exclusive with `host`/`port` Resolves swift-server#69
Motivation: The UDS bind path was typed as a plain String. A System.FilePath gives it a strongly-typed, path-aware API at the configuration boundary. Modifications: - BindTarget.unixDomainSocket(path:) and its backing now take a FilePath - Convert to String only at the NIO edge (bind(unixDomainSocketPath:) and fileIO.unlink), where NIO still requires a String - public import System where FilePath appears in public API; plain import elsewhere - Update UDS tests to pass a FilePath Result: The UDS bind path is strongly typed; string literals still work via ExpressibleByStringLiteral, so call sites are unchanged.
Motivation: SocketAddress.init(_:) folded address, port and pathname lookups into a single tuple switch with coarse error cases, making failure reasons ambiguous and leaving the mapping untested. Modifications: - Replace addressOrPortNotAvailable/unsupportedAddressType with the more precise addressNotAvailable and portNotAvailable cases - Rebuild init(_:) around per-field throwing accessors and an exhaustive switch over the address kind - Switch the NIOClient test helper over SocketAddress.base instead of the optional host/port/path accessors - Add SocketAddressTests covering the IPv4, IPv6, UDS and nil mappings Result: Listening-address construction has precise error reasons and unit-test coverage; behaviour is unchanged.
cb49c66 to
b65b663
Compare
Switch connectToTestSecureUpgradeHTTPServer over SocketAddress.base like the HTTP/1.1 helper, and drop the now-unused TestError.unsupportedAddress.
0xTim
left a comment
There was a problem hiding this comment.
Looking mostly good, I think we should add H2 support as well though
… HTTP/3 Merges swift-server#101 and rejects unix domain socket bind targets when HTTP/3 is enabled, since HTTP/3 runs over QUIC/UDP.
| ) | ||
| } | ||
| serverChannels.append((serverChannel, serverQuiescingHelper)) | ||
| case .unixDomainSocket(let path): |
There was a problem hiding this comment.
To avoid duplication with the case above, we should define an extension on ServerBootstrap's bind method that accepts a NIOHTTPServerConfiguration.BindTarget. That method should switch over the bind target and call into either the host and port variant or the UDS variant of ServerBootstrap.bind.
| ) | ||
| } | ||
| serverChannels.append((serverChannel, serverQuiescingHelper)) | ||
| case .unixDomainSocket(let path): |
There was a problem hiding this comment.
Same as above. You will be able to use the extension here too.
Resolve test-client conflicts, fix HTTP/3 test client for optional SocketAddress host/port, and dedup ServerBootstrap.bind via a BindTarget-aware helper.
NIO unlinks the socket path when the listening socket closes, so our own unlink always ran too late: it logged a spurious failure and could delete a path another process had since bound Added a request-response test over a UDS, parameterised over plaintext HTTP/1.1, HTTP/1.1 and HTTP/2
`import System` is Darwin-only; depend on swift-system and import SystemPackage so Linux builds. Also enforce the UDS/HTTP/3 rule when `bindTargets` or `supportedHTTPVersions` is set after creation, not only in init.
Motivation
NIOHTTPServercould only bind to a host and port, but serving over a UNIX domain socket is a common requirement (e.g. a reverse proxy over a local socket). Resolves #69Modifications
BindTarget.unixDomainSocket(path:)and a matchingSocketAddresscase, bound through the existing listener path so HTTP/1.1 and HTTP/2 need no UDS-specific handlingSocketAddress.host/.portare now optional (source-breaking): a UDS address has neithersocketPathkey to swift-configuration and a configuration error for UDS with HTTP/3Result
NIOHTTPServercan listen on a UNIX domain socket over HTTP/1.1 and HTTP/2, and reports the bound path fromlisteningAddresses