Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Kitura-NIO to only listen on one network address #205

Merged
merged 4 commits into from
May 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Sources/KituraNet/FastCGI/FastCGIServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public class FastCGIServer: Server {
/// Port number for listening for new connections
public private(set) var port: Int?

/// The address of a network interface to listen on, for example "localhost". The default is nil,
/// which listens for connections on all interfaces.
public private(set) var address: String?

/// A server state.
public private(set) var state: ServerState = .unknown

Expand All @@ -53,17 +57,21 @@ public class FastCGIServer: Server {
/// Listens for connections on a socket
///
/// - Parameter on: port number for new connections
public func listen(on port: Int) throws {
/// - Parameter address: The address of the network interface to listen on. Defaults to nil, which means this
/// server will listen on all interfaces.
public func listen(on port: Int, address: String? = nil) throws {
fatalError("FastCGI is not implemented yet.")
}

/// Static method to create a new `FastCGIServer` and have it listen for conenctions
///
/// - Parameter on: port number for accepting new connections
/// - Parameter address: The address of the network interface to listen on. Defaults to nil, which means this
/// server will listen on all interfaces.
/// - Parameter delegate: the delegate handler for FastCGI/HTTP connections
///
/// - Returns: a new `FastCGIServer` instance
public static func listen(on port: Int, delegate: ServerDelegate?) throws -> FastCGIServer {
public static func listen(on port: Int, address: String? = nil, delegate: ServerDelegate?) throws -> FastCGIServer {
fatalError("FastCGI not implemented yet.")
}

Expand Down
31 changes: 20 additions & 11 deletions Sources/KituraNet/HTTP/HTTPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public class HTTPServer: Server {
/// The TCP port on which this server listens for new connections. If `nil`, this server does not listen on a TCP socket.
public private(set) var port: Int?

/// The address of a network interface to listen on, for example "localhost". The default is nil,
/// which listens for connections on all interfaces.
public private(set) var address: String?

/// The Unix domain socket path on which this server listens for new connections. If `nil`, this server does not listen on a Unix socket.
public private(set) var unixDomainSocketPath: String?

Expand Down Expand Up @@ -232,8 +236,8 @@ public class HTTPServer: Server {

// Sockets could either be TCP/IP sockets or Unix domain sockets
private enum SocketType {
// An TCP/IP socket has an associated port number
case tcp(Int)
// An TCP/IP socket has an associated port number and optional address value
case tcp(Int, String?)
// A unix domain socket has an associated filename
case unix(String)
}
Expand All @@ -258,14 +262,17 @@ public class HTTPServer: Server {

### Usage Example: ###
````swift
try server.listen(on: 8080)
try server.listen(on: 8080, address: "localhost")
````

- Parameter on: Port number for new connections, e.g. 8080
*/
public func listen(on port: Int) throws {
- Parameter address: The address of the network interface to listen on. Defaults to nil, which means this server
will listen on all interfaces.
*/
public func listen(on port: Int, address: String? = nil) throws {
self.port = port
try listen(.tcp(port))
self.address = address
try listen(.tcp(port, address))
}

private func listen(_ socket: SocketType) throws {
Expand Down Expand Up @@ -310,8 +317,8 @@ public class HTTPServer: Server {
let listenerDescription: String
do {
switch socket {
case SocketType.tcp(let port):
serverChannel = try bootstrap.bind(host: "0.0.0.0", port: port).wait()
case SocketType.tcp(let port, let address):
serverChannel = try bootstrap.bind(host: address ?? "0.0.0.0", port: port).wait()
self.port = serverChannel?.localAddress?.port.map { Int($0) }
listenerDescription = "port \(self.port ?? port)"
case SocketType.unix(let unixDomainSocketPath):
Expand Down Expand Up @@ -360,18 +367,20 @@ public class HTTPServer: Server {

### Usage Example: ###
````swift
let server = HTTPServer.listen(on: 8080, delegate: self)
let server = HTTPServer.listen(on: 8080, node: "localhost", delegate: self)
````

- Parameter on: Port number for accepting new connections.
- Parameter address: The address of the network interface to listen on. Defaults to nil, which means this server
will listen on all interfaces.
- Parameter delegate: The delegate handler for HTTP connections.

- Returns: A new instance of a `HTTPServer`.
*/
public static func listen(on port: Int, delegate: ServerDelegate?) throws -> ServerType {
public static func listen(on port: Int, address: String? = nil, delegate: ServerDelegate?) throws -> ServerType {
let server = HTTP.createServer()
server.delegate = delegate
try server.listen(on: port)
try server.listen(on: port, address: address)
return server
}

Expand Down
30 changes: 30 additions & 0 deletions Sources/KituraNet/Server/Server.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,35 @@ public protocol Server {
/// Port number for listening for new connections.
var port: Int? { get }

/// The address of a network interface to listen on, for example "localhost". The default is nil,
/// which listens for connections on all interfaces.
var address: String? { get }

/// A server state.
var state: ServerState { get }

/// Listen for connections on a socket.
///
/// - Parameter on: port number for new connections (eg. 8080)
/// - Parameter address: The address of the network interface to listen on. Defaults to nil, which means this
/// server will listen on all interfaces.
func listen(on port: Int, address: String?) throws

/// Listen for connections on a socket.
///
/// - Parameter on: port number for new connections (eg. 8080)
func listen(on port: Int) throws

/// Static method to create a new Server and have it listen for connections.
///
/// - Parameter on: port number for accepting new connections
/// - Parameter address: The address of the network interface to listen on. Defaults to nil, which means this
/// server will listen on all interfaces.
/// - Parameter delegate: the delegate handler for HTTP connections
///
/// - Returns: a new Server instance
static func listen(on port: Int, address: String?, delegate: ServerDelegate?) throws -> ServerType

/// Static method to create a new Server and have it listen for connections.
///
/// - Parameter on: port number for accepting new connections
Expand Down Expand Up @@ -94,3 +115,12 @@ public protocol Server {
@discardableResult
func clientConnectionFailed(callback: @escaping (Swift.Error) -> Void) -> Self
}

extension Server {
public func listen(on port: Int) throws {
try listen(on: port, address: nil)
}
public static func listen(on port: Int, delegate: ServerDelegate?) throws -> ServerType {
return try Self.listen(on: port, address: nil, delegate: delegate)
}
}
2 changes: 1 addition & 1 deletion Tests/KituraNetTests/ClientE2ETests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class ClientE2ETests: KituraNetTest {

func testEphemeralListeningPort() {
do {
let server = try HTTPServer.listen(on: 0, delegate: delegate)
let server = try HTTPServer.listen(on: 0, address: "localhost", delegate: delegate)
_ = HTTP.get("http://localhost:\(server.port!)") { response in
XCTAssertNotNil(response, "ERROR!!! ClientRequest response object was nil")
XCTAssertEqual(response?.statusCode, HTTPStatusCode.OK, "HTTP Status code was \(String(describing: response?.statusCode))")
Expand Down
2 changes: 1 addition & 1 deletion Tests/KituraNetTests/KituraNIOTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class KituraNetTest: XCTestCase {
try server.listen(unixDomainSocketPath: unixDomainSocketPath)
} else {
server.allowPortReuse = allowPortReuse
try server.listen(on: port)
try server.listen(on: port, address: "localhost")
}
return server
}
Expand Down
6 changes: 3 additions & 3 deletions Tests/KituraNetTests/LifecycleListenerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class LifecycleListenerTests: KituraNetTest {
}

do {
try server.listen(on: 0)
try server.listen(on: 0, address: "localhost")

self.waitForExpectations(timeout: 5) { error in
XCTAssertNil(error)
Expand Down Expand Up @@ -127,7 +127,7 @@ class LifecycleListenerTests: KituraNetTest {
}

do {
try server.listen(on: 0)
try server.listen(on: 0, address: "localhost")

self.waitForExpectations(timeout: 5) { error in
XCTAssertNil(error)
Expand Down Expand Up @@ -155,7 +155,7 @@ class LifecycleListenerTests: KituraNetTest {
})

do {
try server.listen(on: -1)
try server.listen(on: -1, address: nil)
} catch {
// Do NOT fail the test if an error is thrown.
// In this test case an error should be thrown.
Expand Down
2 changes: 1 addition & 1 deletion Tests/KituraNetTests/MonitoringTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class MonitoringTests: KituraNetTest {
}

do {
try server.listen(on: 0)
try server.listen(on: 0, address: nil)
self.waitForExpectations(timeout: 10) { error in
server.stop()
XCTAssertNil(error)
Expand Down
4 changes: 2 additions & 2 deletions Tests/KituraNetTests/PipeliningTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class PipeliningTests: KituraNetTest {
let server = HTTPServer()
server.delegate = Delegate()
do {
try server.listen(on: 0)
try server.listen(on: 0, address: "localhost")
} catch let error {
Log.error("Server failed to listen. Error: \(error)")
}
Expand Down Expand Up @@ -85,7 +85,7 @@ class PipeliningTests: KituraNetTest {
server.delegate = Delegate()
server.delegate = Delegate()
do {
try server.listen(on: 0)
try server.listen(on: 0, address: "localhost")
} catch let error {
Log.error("Server failed to listen. Error: \(error)")
}
Expand Down