Skip to content

Commit

Permalink
Allow Kitura-NIO to only listen on one network address (#205)
Browse files Browse the repository at this point in the history
Allow Kitura-NIO to only listen on one network address

* Pass through node to bootstrap.bind().

* 1. Change node to address. 2. Remove extra code.

* Better documentation comments.

* Make funtion signatures for FastCGIServer and HTTPServer match Kitura-Net exactly.
  • Loading branch information
TaborKelly authored and Pushkar N Kulkarni committed May 24, 2019
1 parent b61c6d4 commit 61b29ed
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 21 deletions.
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

0 comments on commit 61b29ed

Please sign in to comment.