From 3be6f16136de572d94c26373452dad1ad526462b Mon Sep 17 00:00:00 2001 From: Nethra Ravindran Date: Thu, 6 Sep 2018 02:42:50 -0700 Subject: [PATCH 1/2] Refactor - HTTPServer upgrade handlers --- Sources/KituraNet/HTTP/HTTPServer.swift | 43 ++++++++++++++++--------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/Sources/KituraNet/HTTP/HTTPServer.swift b/Sources/KituraNet/HTTP/HTTPServer.swift index 533a3348..81485553 100644 --- a/Sources/KituraNet/HTTP/HTTPServer.swift +++ b/Sources/KituraNet/HTTP/HTTPServer.swift @@ -68,6 +68,8 @@ public class HTTPServer : Server { /// The event loop group on which the HTTP handler runs let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) + private var ctx: ChannelHandlerContext? + public init() { } /// SSL cert configs for handling client requests @@ -90,6 +92,28 @@ public class HTTPServer : Server { /// URI for which the latest WebSocket upgrade was requested by a client var latestWebSocketURI: String? + /// Determines if the request should be upgraded and adds additional upgrade headers to the request + private func shouldUpgradeToWebSocket(webSocketHandlerFactory: ProtocolHandlerFactory, head: HTTPRequestHead) -> HTTPHeaders? { + self.latestWebSocketURI = head.uri + guard webSocketHandlerFactory.isServiceRegistered(at: head.uri) else { return nil } + var headers = HTTPHeaders() + if let wsProtocol = head.headers["Sec-WebSocket-Protocol"].first { + headers.add(name: "Sec-WebSocket-Protocol", value: wsProtocol) + } + if let key = head.headers["Sec-WebSocket-Key"].first { + headers.add(name: "Sec-WebSocket-Key", value: key) + } + return headers + } + + /// Creates upgrade request and adds WebSocket handler to pipeline + private func upgradeHandler(webSocketHandlerFactory: ProtocolHandlerFactory, request: HTTPRequestHead) -> EventLoopFuture { + guard let ctx = self.ctx else { fatalError("Cannot create ServerRequest") } + ///TODO: Handle secure upgrade request ("wss://") + let serverRequest = HTTPServerRequest(ctx: ctx, requestHead: request, enableSSL: false) + return ctx.channel.pipeline.add(handler: webSocketHandlerFactory.handler(for: serverRequest)) + } + /// Listens for connections on a socket /// /// - Parameter on: port number for new connections (eg. 8080) @@ -100,26 +124,13 @@ public class HTTPServer : Server { self.sslContext = try! SSLContext(configuration: tlsConfig) } - var channelHandlerCtx: ChannelHandlerContext? var upgraders: [HTTPProtocolUpgrader] = [] if let webSocketHandlerFactory = ConnectionUpgrader.getProtocolHandlerFactory(for: "websocket") { ///TODO: Should `maxFrameSize` be configurable? let upgrader = KituraWebSocketUpgrader(maxFrameSize: 1 << 24, automaticErrorHandling: false, shouldUpgrade: { (head: HTTPRequestHead) in - self.latestWebSocketURI = head.uri - guard webSocketHandlerFactory.isServiceRegistered(at: head.uri) else { return nil } - var headers = HTTPHeaders() - if let wsProtocol = head.headers["Sec-WebSocket-Protocol"].first { - headers.add(name: "Sec-WebSocket-Protocol", value: wsProtocol) - } - if let key = head.headers["Sec-WebSocket-Key"].first { - headers.add(name: "Sec-WebSocket-Key", value: key) - } - return headers + return self.shouldUpgradeToWebSocket(webSocketHandlerFactory: webSocketHandlerFactory, head: head) }, upgradePipelineHandler: { (channel: Channel, request: HTTPRequestHead) in - guard let ctx = channelHandlerCtx else { fatalError("Cannot create ServerRequest") } - ///TODO: Handle secure upgrade request ("wss://") - let serverRequest = HTTPServerRequest(ctx: ctx, requestHead: request, enableSSL: false) - return channel.pipeline.add(handler: webSocketHandlerFactory.handler(for: serverRequest)) + return self.upgradeHandler(webSocketHandlerFactory: webSocketHandlerFactory, request: request) }) upgraders.append(upgrader) } @@ -135,7 +146,7 @@ public class HTTPServer : Server { .childChannelInitializer { channel in let httpHandler = HTTPRequestHandler(for: self) let config: HTTPUpgradeConfiguration = (upgraders: upgraders, completionHandler: { ctx in - channelHandlerCtx = ctx + self.ctx = ctx _ = channel.pipeline.remove(handler: httpHandler) }) return channel.pipeline.add(handler: IdleStateHandler(allTimeout: TimeAmount.seconds(Int(HTTPRequestHandler.keepAliveTimeout)))).then { From 97772c6148e9494328fbb42c4ef2d5377345168d Mon Sep 17 00:00:00 2001 From: Nethra Ravindran Date: Fri, 7 Sep 2018 01:22:39 -0700 Subject: [PATCH 2/2] Default HTTPVersion to 1 --- Sources/KituraNet/HTTP/HTTPServerResponse.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/KituraNet/HTTP/HTTPServerResponse.swift b/Sources/KituraNet/HTTP/HTTPServerResponse.swift index 93f1f0df..e5131728 100644 --- a/Sources/KituraNet/HTTP/HTTPServerResponse.swift +++ b/Sources/KituraNet/HTTP/HTTPServerResponse.swift @@ -60,8 +60,8 @@ public class HTTPServerResponse: ServerResponse { self.channel = channel self.handler = handler self.buffer = channel.allocator.buffer(capacity: HTTPServerResponse.bufferSize) - let httpVersionMajor = handler.serverRequest?.httpVersionMajor ?? 0 - let httpVersionMinor = handler.serverRequest?.httpVersionMinor ?? 0 + let httpVersionMajor = handler.serverRequest?.httpVersionMajor ?? 1 + let httpVersionMinor = handler.serverRequest?.httpVersionMinor ?? 1 self.httpVersion = HTTPVersion(major: httpVersionMajor, minor: httpVersionMinor) headers["Date"] = [SPIUtils.httpDate()] }