Skip to content

Commit

Permalink
Merge branch 'master' into limitRequestSize
Browse files Browse the repository at this point in the history
  • Loading branch information
RudraniW authored Aug 27, 2019
2 parents 765ef49 + 9710e0a commit 83523b5
Show file tree
Hide file tree
Showing 13 changed files with 333 additions and 71 deletions.
2 changes: 1 addition & 1 deletion .swift-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.0.1
5.0.2
14 changes: 7 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,32 @@ matrix:
dist: xenial
sudo: required
services: docker
env: DOCKER_IMAGE=swift:5.0.1-xenial DOCKER_PRIVILEGED=true CUSTOM_TEST_SCRIPT=.kitura-test.sh
env: DOCKER_IMAGE=swift:5.0.2-xenial DOCKER_PRIVILEGED=true CUSTOM_TEST_SCRIPT=.kitura-test.sh
- os: linux
dist: xenial
sudo: required
services: docker
env: DOCKER_IMAGE=swift:5.0.1-xenial DOCKER_PRIVILEGED=true SWIFT_TEST_ARGS="--parallel"
env: DOCKER_IMAGE=swift:5.0.2-xenial DOCKER_PRIVILEGED=true SWIFT_TEST_ARGS="--parallel"
- os: linux
dist: xenial
sudo: required
services: docker
env: DOCKER_IMAGE=swift:5.0.1 DOCKER_PRIVILEGED=true SWIFT_TEST_ARGS="--parallel"
env: DOCKER_IMAGE=swift:5.0.2 DOCKER_PRIVILEGED=true SWIFT_TEST_ARGS="--parallel"
- os: linux
dist: xenial
sudo: required
services: docker
env: DOCKER_IMAGE=swift:5.0.1 SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT DOCKER_PRIVILEGED=true SWIFT_TEST_ARGS="--parallel"
env: DOCKER_IMAGE=swift:5.0.2 SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT DOCKER_PRIVILEGED=true SWIFT_TEST_ARGS="--parallel"
- os: osx
osx_image: xcode10.2
sudo: required
env: JAZZY_ELIGIBLE=true SWIFT_TEST_ARGS="--parallel"
env: SWIFT_SNAPSHOT=5.0.1 JAZZY_ELIGIBLE=true SWIFT_TEST_ARGS="--parallel" CUSTOM_TEST_SCRIPT=.kitura-test.sh
- os: osx
osx_image: xcode10.2
osx_image: xcode11
sudo: required
env: SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT SWIFT_TEST_ARGS="--parallel"
- os: osx
osx_image: xcode10.2
osx_image: xcode11
sudo: required
env: SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT CUSTOM_TEST_SCRIPT=.kitura-test.sh

Expand Down
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(url: "https://github.com/apple/swift-nio.git", from: "2.1.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.3.0"),
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.0.0"),
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.0.0"),
.package(url: "https://github.com/IBM-Swift/BlueSSLService.git", from: "1.0.0"),
.package(url: "https://github.com/IBM-Swift/LoggerAPI.git", from: "1.7.3"),
],
Expand Down
21 changes: 19 additions & 2 deletions Sources/KituraNet/ClientRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,20 @@ public class ClientRequest {
}
self.path = fullPath

if let username = url.user {
self.userName = username
}

if let password = url.password {
self.password = password
}

if let username = self.userName, let password = self.password {
self.headers["Authorization"] = createHTTPBasicAuthHeader(username: username, password: password)
}

self.url = "\(scheme)\(self.hostName ?? "unknown")\(self.port.map { ":\($0)" } ?? "")\(fullPath)"
self.url = "\(url.scheme ?? "http")://\(self.hostName ?? "unknown")\(self.port.map { ":\($0)" } ?? "")/\(fullPath)"


}

Expand Down Expand Up @@ -546,8 +555,16 @@ public class ClientRequest {
}

let hostName = URL(string: percentEncodedURL)?.host ?? "" //TODO: what could be the failure path here
let portNumber = URL(string: percentEncodedURL)?.port ?? 8080
if self.headers["Host"] == nil {
self.headers["Host"] = hostName
let isNotDefaultPort = (portNumber != 443 && portNumber != 80) //Check whether port is not 443/80
self.headers["Host"] = hostName + (isNotDefaultPort ? (":" + String(portNumber)) : "")
}

// To keep Kitura-NIO's behaviour similar to Kitura-net, add the Accept header with default value '*/*'.
// Note:libcurl adds default value for Accept header for Kitura-net
if self.headers["Accept"] == nil && self.headers["accept"] == nil {
self.headers["Accept"] = "*/*"
}

self.headers["User-Agent"] = "Kitura"
Expand Down
7 changes: 2 additions & 5 deletions Sources/KituraNet/ClientResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,13 @@ public class ClientResponse {
}
}
/// The HTTP Status code, as an Int, sent in the response by the remote server.
public internal(set) var status = -1 {
didSet {
statusCode = HTTPStatusCode(rawValue: status) ?? .unknown
}
}
public internal(set) var status = -1

/// The HTTP Status code, as an `HTTPStatusCode`, sent in the response by the remote server.
public internal(set) var statusCode: HTTPStatusCode = HTTPStatusCode.unknown {
didSet {
httpStatusCode = statusCode
status = statusCode.rawValue
}
}

Expand Down
45 changes: 30 additions & 15 deletions Sources/KituraNet/HTTP/HTTPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public class HTTPServer: Server {
/// The event loop group on which the HTTP handler runs
private let eventLoopGroup: MultiThreadedEventLoopGroup

private var ctx: ChannelHandlerContext?
var quiescingHelper: ServerQuiescingHelper?

/// server configuration
public var serverConfig: HTTPServerConfiguration
Expand Down Expand Up @@ -202,19 +202,21 @@ public class HTTPServer: Server {
}

/// Creates upgrade request and adds WebSocket handler to pipeline
private func upgradeHandler(webSocketHandlerFactory: ProtocolHandlerFactory, request: HTTPRequestHead) -> EventLoopFuture<Void> {
guard let ctx = self.ctx else { fatalError("Cannot create ServerRequest") }
let serverRequest = HTTPServerRequest(ctx: ctx, requestHead: request, enableSSL: false)
let websocketConnectionHandler = webSocketHandlerFactory.handler(for: serverRequest)
let future = ctx.channel.pipeline.addHandler(websocketConnectionHandler)
if let _extensions = request.headers["Sec-WebSocket-Extensions"].first {
for handler in webSocketHandlerFactory.extensionHandlers(header: _extensions) {
_ = future.flatMap {
ctx.channel.pipeline.addHandler(handler, position: .before(websocketConnectionHandler))
private func upgradeHandler(channel: Channel, webSocketHandlerFactory: ProtocolHandlerFactory, request: HTTPRequestHead) -> EventLoopFuture<Void> {
return channel.eventLoop.submit {
let request = HTTPServerRequest(channel: channel, requestHead: request, enableSSL: false)
return webSocketHandlerFactory.handler(for: request)
}.flatMap { (handler: ChannelHandler) -> EventLoopFuture<Void> in
return channel.pipeline.addHandler(handler).flatMap {
if let _extensions = request.headers["Sec-WebSocket-Extensions"].first {
let handlers = webSocketHandlerFactory.extensionHandlers(header: _extensions)
return channel.pipeline.addHandlers(handlers, position: .before(handler))
} else {
// No extensions. We must return success.
return channel.eventLoop.makeSucceededFuture(())
}
}
}
}
return future
}

private typealias ShouldUpgradeFunction = (Channel, HTTPRequestHead) -> EventLoopFuture<HTTPHeaders?>
Expand All @@ -228,7 +230,7 @@ public class HTTPServer: Server {

private func generateUpgradePipelineHandler(_ webSocketHandlerFactory: ProtocolHandlerFactory) -> UpgradePipelineHandlerFunction {
return { (channel: Channel, request: HTTPRequestHead) in
return self.upgradeHandler(webSocketHandlerFactory: webSocketHandlerFactory, request: request)
return self.upgradeHandler(channel: channel, webSocketHandlerFactory: webSocketHandlerFactory, request: request)
}
}

Expand Down Expand Up @@ -308,8 +310,14 @@ public class HTTPServer: Server {
.serverChannelOption(ChannelOptions.backlog, value: BacklogOption.Value(self.maxPendingConnections))
.serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
.serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEPORT), value: allowPortReuse ? 1 : 0)
.serverChannelInitializer { channel in
// Adding the quiescing helper will help us do a graceful stop()
self.quiescingHelper = ServerQuiescingHelper(group: self.eventLoopGroup)
return channel.pipeline.addHandler(self.quiescingHelper!.makeServerChannelHandler(channel: channel))
}
.childChannelInitializer { channel in
let httpHandler = HTTPRequestHandler(for: self)

let serverConfigurationHandler = HTTPServerConfigurationHandler(for: self)
let config: HTTPUpgradeConfiguration = (upgraders: upgraders, completionHandler: { ctx in
self.ctx = ctx
Expand All @@ -322,7 +330,6 @@ public class HTTPServer: Server {
return channel.pipeline.addHandler(httpHandler) }
}
.childChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)


let listenerDescription: String
do {
Expand Down Expand Up @@ -475,13 +482,21 @@ public class HTTPServer: Server {
````
*/
public func stop() {
// Close the listening channel
guard let serverChannel = serverChannel else { return }
do {
try serverChannel.close().wait()
} catch let error {
Log.error("Failed to close the server channel. Error: \(error)")
}
self.state = .stopped

// Now close all the open channels
guard let quiescingHelper = self.quiescingHelper else { return }
let fullShutdownPromise: EventLoopPromise<Void> = eventLoopGroup.next().makePromise()
quiescingHelper.initiateShutdown(promise: fullShutdownPromise)
fullShutdownPromise.futureResult.whenComplete { _ in
self.state = .stopped
}
}

/**
Expand Down
51 changes: 19 additions & 32 deletions Sources/KituraNet/HTTP/HTTPServerRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,31 +115,19 @@ public class HTTPServerRequest: ServerRequest {
var url = ""
url.append(self.enableSSL ? "https://" : "http://")

var localAddress = ""
var localAddressPort = 0

do {
try ctx.eventLoop.runAndWait {
localAddress = HTTPServerRequest.host(socketAddress: self.ctx.localAddress)
localAddressPort = self.ctx.localAddress?.port ?? 0
}
} catch {
Log.error("Unable to get the local address")
}

if let hostname = headers["Host"]?.first {
// Handle Host header values of the kind "localhost:8080"
url.append(hostname)
if !hostname.contains(":") {
url.append(":")
url.append(String(describing: localAddressPort))
url.append(String(describing: self.localAddressPort))
}
} else {
Log.error("Host header not received")
let hostname = localAddress
let hostname = self.localAddressHost
url.append(hostname == "127.0.0.1" ? "localhost" : hostname)
url.append(":")
url.append(String(describing: localAddressPort))
url.append(String(describing: self.localAddressPort))
}
url.append(rawURLString)

Expand All @@ -152,8 +140,6 @@ public class HTTPServerRequest: ServerRequest {
return self._url!
}

private var _remoteAddress: String?

/**
Server IP address pulled from socket.

Expand All @@ -162,18 +148,7 @@ public class HTTPServerRequest: ServerRequest {
request.remoteAddress
````
*/
public var remoteAddress: String {
if _remoteAddress == nil {
do {
try ctx.eventLoop.runAndWait {
self._remoteAddress = HTTPServerRequest.host(socketAddress: self.ctx.remoteAddress)
}
} catch {
Log.error("Unable to get the remote address")
}
}
return _remoteAddress!
}
public var remoteAddress: String

/**
Major version of HTTP of the request
Expand Down Expand Up @@ -205,14 +180,20 @@ public class HTTPServerRequest: ServerRequest {
*/
public var method: String

private let ctx: ChannelHandlerContext
private let channel: Channel

private var enableSSL: Bool = false

private var rawURLString: String

private var urlStringPercentEncodingRemoved: String?

// The hostname of the server
private var localAddressHost: String

// The port number on which the server is listening
private var localAddressPort: Int

private static func host(socketAddress: SocketAddress?) -> String {
guard let socketAddress = socketAddress else {
return ""
Expand All @@ -227,14 +208,20 @@ public class HTTPServerRequest: ServerRequest {
}
}

init(ctx: ChannelHandlerContext, requestHead: HTTPRequestHead, enableSSL: Bool) {
self.ctx = ctx
init(channel: Channel, requestHead: HTTPRequestHead, enableSSL: Bool) {
// An HTTPServerRequest may be created only on the EventLoop assigned to handle
// the connection on which the HTTP request arrived.
assert(channel.eventLoop.inEventLoop)
self.channel = channel
self.headers = HeadersContainer(with: requestHead.headers)
self.method = requestHead.method.rawValue
self.httpVersionMajor = UInt16(requestHead.version.major)
self.httpVersionMinor = UInt16(requestHead.version.minor)
self.rawURLString = requestHead.uri
self.enableSSL = enableSSL
self.localAddressHost = HTTPServerRequest.host(socketAddress: channel.localAddress)
self.localAddressPort = channel.localAddress?.port ?? 0
self.remoteAddress = HTTPServerRequest.host(socketAddress: channel.remoteAddress)
}

var buffer: BufferList?
Expand Down
5 changes: 0 additions & 5 deletions Sources/KituraNet/HTTP/HTTPServerResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,4 @@ extension EventLoop {
}
}
}

func runAndWait(_ task: @escaping () -> Void) throws {
guard let eventLoopFuture = run(task) else { return }
try eventLoopFuture.wait()
}
}
Loading

0 comments on commit 83523b5

Please sign in to comment.