diff --git a/.travis.yml b/.travis.yml index 19a3a57..9a469ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ branches: notifications: slack: - secure: "rbi1R2Icz5jsIo5YsFmRFyhjb+sJgAXHYQEdRE508oRjANhvOJ0JwIbDLLOT4w3lN1AAIWFaEP/el3UN9F/ZNCUqYiduXfpS3clagYVlG3gjFruLOnVIT85ubazYcLqMNvbhGRJvMyHUroCIIg3qPeCoF77UkA6WKhsgfbD1Oa6PkO+o1R4TAb2h5YUZbuvRan/4MUu6eSUj7bQ0qbB+viSAYDZCn0saMcj7v4n3HI+RiQkVN1HFkaSUBSRGLJYGd+kGwEAp3sqN0lSkAWPyteblzaXAvpobO+fQrTiBGVJoln+1ITesCvPMlEbXW2g+Yldb+wtr2dsDMLtcj7PVlKKanmEfz7bst0hw2SXShoarnW2LBo9AzQNpl/XF6GuGu3VT/KdP4M9hg6wuXCmmFSrPLM8mSdcenIlCOdO1h7nV+LRaSGLJzKIQGDUdFPpw6WoKJ/WKMWd7E6q9JLDffRY5C8IeekC7tLxMn5ZKMPZaM6yAzBkS/USlR34BuyrTQcvv707aJF/UaZXmhDZ72/3uN2zMdSpVWXVWwGmayRnDNrTeGe2wMe2AdnZC43V0MmS3a88AQGl3E1IDgrVBtIZJ0wTax/rCFU1ePNH/KErdFcaJ4s4v0Pv4WR4I2JYKQ6rSblV477DBi2ZJv+G/yaOXhwE+6gRqIHy73pG4YTU=" + secure: "rbi1R2Icz5jsIo5YsFmRFyhjb+sJgAXHYQEdRE508oRjANhvOJ0JwIbDLLOT4w3lN1$ matrix: include: diff --git a/Package.swift b/Package.swift index 64042ed..6caf912 100644 --- a/Package.swift +++ b/Package.swift @@ -19,10 +19,10 @@ import PackageDescription let package = Package( name: "Kitura-net", dependencies: [ - .Package(url: "https://github.com/IBM-Swift/Kitura-sys.git", majorVersion: 0, minor: 10), - .Package(url: "https://github.com/IBM-Swift/BlueSocket.git", majorVersion: 0, minor: 3), - .Package(url: "https://github.com/IBM-Swift/LoggerAPI.git", majorVersion: 0, minor: 4), - .Package(url: "https://github.com/IBM-Swift/CCurl.git", majorVersion: 0, minor: 0), - .Package(url: "https://github.com/IBM-Swift/CHttpParser.git", majorVersion: 0, minor: 0), + .Package(url: "https://github.com/IBM-Swift/Kitura-sys.git", majorVersion: 0, minor: 12), + .Package(url: "https://github.com/IBM-Swift/BlueSocket.git", majorVersion: 0, minor: 5), + .Package(url: "https://github.com/IBM-Swift/LoggerAPI.git", majorVersion: 0, minor: 5), + .Package(url: "https://github.com/IBM-Swift/CCurl.git", majorVersion: 0, minor: 1), + .Package(url: "https://github.com/IBM-Swift/CHttpParser.git", majorVersion: 0, minor: 1), ] ) diff --git a/Sources/KituraNet/BufferList.swift b/Sources/KituraNet/BufferList.swift index 9b79349..02e8ab4 100644 --- a/Sources/KituraNet/BufferList.swift +++ b/Sources/KituraNet/BufferList.swift @@ -65,8 +65,8 @@ public class BufferList { /// Parameter bytes: a pointer to the array /// Parameter length: number of bytes in the array /// - public func appendBytes(bytes: UnsafePointer, length: Int) { - lclData!.appendBytes(bytes, length: length) + public func append(bytes: UnsafePointer, length: Int) { + lclData!.append(bytes, length: length) } /// @@ -74,8 +74,8 @@ public class BufferList { /// /// Parameter data: The data to append /// - public func appendData(data: NSData) { - lclData!.appendBytes(data.bytes, length: data.length) + public func append(data: NSData) { + lclData!.append(data.bytes, length: data.length) } /// @@ -85,10 +85,10 @@ public class BufferList { /// /// - Returns: /// - public func fillArray(buffer: inout [UInt8]) -> Int { + public func fill(array: inout [UInt8]) -> Int { - let result = min(buffer.count, lclData!.length-byteIndex) - memcpy(UnsafeMutablePointer(buffer), lclData!.bytes+byteIndex, Int(result)) + let result = min(array.count, lclData!.length-byteIndex) + memcpy(UnsafeMutablePointer(array), lclData!.bytes+byteIndex, Int(result)) byteIndex += result return result @@ -103,7 +103,7 @@ public class BufferList { /// /// - Returns: /// - public func fillBuffer(buffer: UnsafeMutablePointer, length: Int) -> Int { + public func fill(buffer: UnsafeMutablePointer, length: Int) -> Int { let result = min(length, lclData!.length-byteIndex) memcpy(buffer, lclData!.bytes+byteIndex, Int(result)) @@ -120,10 +120,10 @@ public class BufferList { /// /// - Returns: /// - public func fillData(data: NSMutableData) -> Int { + public func fill(data: NSMutableData) -> Int { let result = lclData!.length-byteIndex - data.appendBytes(lclData!.bytes+byteIndex, length: result) + data.append(lclData!.bytes+byteIndex, length: result) byteIndex += result return result diff --git a/Sources/KituraNet/ClientRequest.swift b/Sources/KituraNet/ClientRequest.swift index 86b8daf..883292d 100644 --- a/Sources/KituraNet/ClientRequest.swift +++ b/Sources/KituraNet/ClientRequest.swift @@ -67,7 +67,7 @@ public class ClientRequest: SocketWriter { /// /// List of header information /// - private var headersList: UnsafeMutablePointer = nil + private var headersList: UnsafeMutablePointer? /// /// BufferList to store bytes to be written @@ -192,7 +192,7 @@ public class ClientRequest: SocketWriter { /// public func write(from data: NSData) { - writeBuffers.appendData(data) + writeBuffers.append(data: data) } @@ -201,7 +201,7 @@ public class ClientRequest: SocketWriter { /// /// - Parameter data: string to send before ending /// - public func end(data: String) { + public func end(_ data: String) { write(from: data) end() @@ -213,7 +213,7 @@ public class ClientRequest: SocketWriter { /// /// - Parameter data: data to send before ending /// - public func end(data: NSData) { + public func end(_ data: NSData) { write(from: data) end() @@ -276,7 +276,7 @@ public class ClientRequest: SocketWriter { /// /// Parameter urlBuf: ??? /// - private func prepareHandle(urlBuf: NSData) { + private func prepareHandle(_ urlBuf: NSData) { handle = curl_easy_init() // HTTP parser does the decoding @@ -288,14 +288,18 @@ public class ClientRequest: SocketWriter { curlHelperSetOptInt(handle!, CURLOPT_POSTFIELDSIZE, count) } setupHeaders() - + let emptyCstring = StringUtils.toNullTerminatedUtf8String("")! + curlHelperSetOptString(handle!, CURLOPT_COOKIEFILE, UnsafeMutablePointer(emptyCstring.bytes)) + + // To see the messages sent by libCurl, uncomment the next line of code + //curlHelperSetOptInt(handle, CURLOPT_VERBOSE, 1) } /// /// Sets the HTTP method in libCurl to the one specified in method /// private func setMethod() { - + let methodUpperCase = method.uppercased() switch(methodUpperCase) { case "GET": @@ -304,18 +308,20 @@ public class ClientRequest: SocketWriter { curlHelperSetOptBool(handle!, CURLOPT_POST, CURL_TRUE) case "PUT": curlHelperSetOptBool(handle!, CURLOPT_PUT, CURL_TRUE) + case "HEAD": + curlHelperSetOptBool(handle!, CURLOPT_NOBODY, CURL_TRUE) default: let methodCstring = StringUtils.toNullTerminatedUtf8String(methodUpperCase)! curlHelperSetOptString(handle!, CURLOPT_CUSTOMREQUEST, UnsafeMutablePointer(methodCstring.bytes)) } - + } /// - /// Sets the headers in libCurl to the ones in headers + /// Sets the headers in libCurl to the ones in headers /// private func setupHeaders() { - + for (headerKey, headerValue) in headers { let headerString = StringUtils.toNullTerminatedUtf8String("\(headerKey): \(headerValue)") if let headerString = headerString { @@ -333,16 +339,16 @@ extension ClientRequest: CurlInvokerDelegate { /// /// - private func curlWriteCallback(buf: UnsafeMutablePointer, size: Int) -> Int { + private func curlWriteCallback(_ buf: UnsafeMutablePointer, size: Int) -> Int { - response.responseBuffers.appendBytes(UnsafePointer(buf), length: size) + response.responseBuffers.append(bytes: UnsafePointer(buf), length: size) return size } - private func curlReadCallback(buf: UnsafeMutablePointer, size: Int) -> Int { + private func curlReadCallback(_ buf: UnsafeMutablePointer, size: Int) -> Int { - let count = writeBuffers.fillBuffer(UnsafeMutablePointer(buf), length: size) + let count = writeBuffers.fill(buffer: UnsafeMutablePointer(buf), length: size) return count } @@ -421,7 +427,7 @@ private class CurlInvoker { rc = curl_easy_perform(handle) if rc == CURLE_OK { - var redirectUrl: UnsafeMutablePointer = nil + var redirectUrl: UnsafeMutablePointer? = nil let infoRc = curlHelperGetInfoCString(handle, CURLINFO_REDIRECT_URL, &redirectUrl) if infoRc == CURLE_OK { if redirectUrl != nil { @@ -447,18 +453,18 @@ private class CurlInvoker { /// /// - Parameter ptr: pointer to the CurlInvokerDelegate /// - private func prepareHandle(ptr: UnsafeMutablePointer) { + private func prepareHandle(_ ptr: UnsafeMutablePointer) { - curlHelperSetOptReadFunc(handle, ptr) { (buf: UnsafeMutablePointer, size: Int, nMemb: Int, privateData: UnsafeMutablePointer) -> Int in + curlHelperSetOptReadFunc(handle, ptr) { (buf: UnsafeMutablePointer!, size: Int, nMemb: Int, privateData: UnsafeMutablePointer!) -> Int in let p = UnsafePointer(privateData) - return (p.pointee?.curlReadCallback(buf, size: size*nMemb))! + return (p?.pointee?.curlReadCallback(buf, size: size*nMemb))! } - curlHelperSetOptWriteFunc(handle, ptr) { (buf: UnsafeMutablePointer, size: Int, nMemb: Int, privateData: UnsafeMutablePointer) -> Int in + curlHelperSetOptWriteFunc(handle, ptr) { (buf: UnsafeMutablePointer!, size: Int, nMemb: Int, privateData: UnsafeMutablePointer!) -> Int in let p = UnsafePointer(privateData) - return (p.pointee?.curlWriteCallback(buf, size: size*nMemb))! + return (p?.pointee?.curlWriteCallback(buf, size: size*nMemb))! } } @@ -469,8 +475,8 @@ private class CurlInvoker { /// private protocol CurlInvokerDelegate: class { - func curlWriteCallback(buf: UnsafeMutablePointer, size: Int) -> Int - func curlReadCallback(buf: UnsafeMutablePointer, size: Int) -> Int + func curlWriteCallback(_ buf: UnsafeMutablePointer, size: Int) -> Int + func curlReadCallback(_ buf: UnsafeMutablePointer, size: Int) -> Int func prepareForRedirect() } diff --git a/Sources/KituraNet/ClientResponse.swift b/Sources/KituraNet/ClientResponse.swift index 7cd988d..384df75 100644 --- a/Sources/KituraNet/ClientResponse.swift +++ b/Sources/KituraNet/ClientResponse.swift @@ -67,9 +67,9 @@ extension ClientResponse: IncomingMessageHelper { /// /// - Returns: ??? /// - func readDataHelper(data: NSMutableData) -> Int { + func readHelper(into data: NSMutableData) -> Int { - return responseBuffers.fillData(data) + return responseBuffers.fill(data: data) } diff --git a/Sources/KituraNet/Http.swift b/Sources/KituraNet/Http.swift index 305df8b..1560f8e 100644 --- a/Sources/KituraNet/Http.swift +++ b/Sources/KituraNet/Http.swift @@ -62,7 +62,7 @@ public class Http { /// /// - Returns: a ClientRequest instance /// - public static func request(url: String, callback: ClientRequestCallback) -> ClientRequest { + public static func request(_ url: String, callback: ClientRequestCallback) -> ClientRequest { return ClientRequest(url: url, callback: callback) @@ -76,7 +76,7 @@ public class Http { /// /// - Returns: a ClientRequest instance /// - public static func request(options: [ClientRequestOptions], callback: ClientRequestCallback) -> ClientRequest { + public static func request(_ options: [ClientRequestOptions], callback: ClientRequestCallback) -> ClientRequest { return ClientRequest(options: options, callback: callback) @@ -91,7 +91,7 @@ public class Http { /// /// - Returns: a ClientRequest instance /// - public static func get(url: String, callback: ClientRequestCallback) -> ClientRequest { + public static func get(_ url: String, callback: ClientRequestCallback) -> ClientRequest { let req = ClientRequest(url: url, callback: callback) req.end() @@ -114,7 +114,7 @@ public class Http { /// *Note*: URLS can only be sent over the Internet using the ASCII character set, so character escaping will /// transform unsafe ASCII characters with a '%' followed by two hexadecimal digits. /// - public static func escapeUrl(url: String) -> String { + public static func escapeUrl(_ url: String) -> String { #if os(Linux) if let escaped = url.bridge().stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) { diff --git a/Sources/KituraNet/HttpParser/HttpParser.swift b/Sources/KituraNet/HttpParser/HttpParser.swift index 42ff8d8..f79226c 100644 --- a/Sources/KituraNet/HttpParser/HttpParser.swift +++ b/Sources/KituraNet/HttpParser/HttpParser.swift @@ -68,28 +68,28 @@ class HttpParser { settings.on_url = { (parser, chunk, length) -> Int32 in let p = UnsafePointer(parser.pointee.data) let data = NSData(bytes: chunk, length: length) - p.pointee?.onUrl(data) + p?.pointee?.onUrl(data) return 0 } settings.on_header_field = { (parser, chunk, length) -> Int32 in let data = NSData(bytes: chunk, length: length) let p = UnsafePointer(parser.pointee.data) - p.pointee?.onHeaderField(data) + p?.pointee?.onHeaderField(data) return 0 } settings.on_header_value = { (parser, chunk, length) -> Int32 in let data = NSData(bytes: chunk, length: length) let p = UnsafePointer(parser.pointee.data) - p.pointee?.onHeaderValue(data) + p?.pointee?.onHeaderValue(data) return 0 } settings.on_body = { (parser, chunk, length) -> Int32 in let p = UnsafePointer(parser.pointee.data) let data = NSData(bytes: chunk, length: length) - p.pointee?.onBody(data) + p?.pointee?.onBody(data) return 0 } @@ -105,7 +105,7 @@ class HttpParser { message += String(UnicodeScalar(UInt8((po+i).pointee))) i += 1 } - p.pointee?.onHeadersComplete(message, versionMajor: parser.pointee.http_major, + p?.pointee?.onHeadersComplete(method: message, versionMajor: parser.pointee.http_major, versionMinor: parser.pointee.http_minor) return 0 @@ -113,7 +113,7 @@ class HttpParser { settings.on_message_begin = { (parser) -> Int32 in let p = UnsafePointer(parser.pointee.data) - p.pointee?.onMessageBegin() + p?.pointee?.onMessageBegin() return 0 } @@ -121,10 +121,10 @@ class HttpParser { settings.on_message_complete = { (parser) -> Int32 in let p = UnsafePointer(parser.pointee.data) if get_status_code(parser) == 100 { - p.pointee?.reset() + p?.pointee?.reset() } else { - p.pointee?.onMessageComplete() + p?.pointee?.onMessageComplete() } return 0 @@ -142,7 +142,7 @@ class HttpParser { /// /// - Returns: ??? /// - func execute (data: UnsafePointer, length: Int) -> (Int, UInt32) { + func execute (_ data: UnsafePointer, length: Int) -> (Int, UInt32) { let nparsed = http_parser_execute(&parser, &settings, data, length) let upgrade = get_upgrade_value(&parser) return (nparsed, upgrade) @@ -154,13 +154,13 @@ class HttpParser { /// protocol HttpParserDelegate: class { - func onUrl(url:NSData) - func onHeaderField(data: NSData) - func onHeaderValue(data: NSData) + func onUrl(_ url:NSData) + func onHeaderField(_ data: NSData) + func onHeaderValue(_ data: NSData) func onHeadersComplete(method: String, versionMajor: UInt16, versionMinor: UInt16) func onMessageBegin() func onMessageComplete() - func onBody(body: NSData) + func onBody(_ body: NSData) func reset() } diff --git a/Sources/KituraNet/HttpParser/UrlParser.swift b/Sources/KituraNet/HttpParser/UrlParser.swift index e336e72..79d4078 100644 --- a/Sources/KituraNet/HttpParser/UrlParser.swift +++ b/Sources/KituraNet/HttpParser/UrlParser.swift @@ -134,14 +134,14 @@ public class UrlParser : CustomStringConvertible { #if os(Linux) let pairs = query.bridge().componentsSeparatedByString("&") #else - let pairs = query.componentsSeparated(by: "&") + let pairs = query.components(separatedBy: "&") #endif for pair in pairs { #if os(Linux) let pairArr = pair.bridge().componentsSeparatedByString("=") #else - let pairArr = pair.componentsSeparated(by: "=") + let pairArr = pair.components(separatedBy: "=") #endif if pairArr.count == 2 { queryParams[pairArr[0]] = pairArr[1] @@ -157,7 +157,7 @@ public class UrlParser : CustomStringConvertible { /// TODO: ??? /// /// - private func getValueFromUrl(url: NSData, fieldSet: UInt16, fieldIndex: UInt16, + private func getValueFromUrl(_ url: NSData, fieldSet: UInt16, fieldIndex: UInt16, fieldData: http_parser_url_field_data) -> String? { if fieldSet & (1 << fieldIndex) != 0 { diff --git a/Sources/KituraNet/HttpServer.swift b/Sources/KituraNet/HttpServer.swift index 7bd5fd7..920b962 100644 --- a/Sources/KituraNet/HttpServer.swift +++ b/Sources/KituraNet/HttpServer.swift @@ -78,7 +78,7 @@ public class HttpServer { do { - self.listenSocket = try Socket.makeDefault() + self.listenSocket = try Socket.create() } catch let error as Socket.Error { print("Error reported:\n \(error.description)") @@ -87,14 +87,14 @@ public class HttpServer { } let queuedBlock = { - self.spi.spiListen(self.listenSocket, port: self._port!) + self.spi.spiListen(socket: self.listenSocket, port: self._port!) } if notOnMainQueue { HttpServer.listenerQueue.queueAsync(queuedBlock) } else { - Queue.queueIfFirstOnMain(HttpServer.listenerQueue, block: queuedBlock) + Queue.queueIfFirstOnMain(queue: HttpServer.listenerQueue, block: queuedBlock) } } @@ -124,7 +124,7 @@ public class HttpServer { let server = Http.createServer() server.delegate = delegate - server.listen(port, notOnMainQueue: notOnMainQueue) + server.listen(port: port, notOnMainQueue: notOnMainQueue) return server } @@ -139,7 +139,7 @@ extension HttpServer : HttpServerSpiDelegate { /// /// - Parameter clientSocket: the socket used for connecting /// - func handleClientRequest(clientSocket: Socket) { + func handleClientRequest(socket clientSocket: Socket) { guard let delegate = delegate else { return @@ -152,7 +152,7 @@ extension HttpServer : HttpServerSpiDelegate { request.parse() { status in switch status { case .Success: - delegate.handleRequest(request, response: response) + delegate.handle(request: request, response: response) case .ParsedLessThanRead: print("ParsedLessThanRead") response.statusCode = .BAD_REQUEST @@ -178,6 +178,6 @@ extension HttpServer : HttpServerSpiDelegate { /// public protocol HttpServerDelegate: class { - func handleRequest(request: ServerRequest, response: ServerResponse) + func handle(request: ServerRequest, response: ServerResponse) } diff --git a/Sources/KituraNet/HttpServerSpi.swift b/Sources/KituraNet/HttpServerSpi.swift index 8caa06f..6a8ad6e 100644 --- a/Sources/KituraNet/HttpServerSpi.swift +++ b/Sources/KituraNet/HttpServerSpi.swift @@ -52,7 +52,7 @@ class HttpServerSpi { let clientSocket = try socket.acceptClientConnection() Log.info("Accepted connection from: " + "\(clientSocket.remoteHostname):\(clientSocket.remotePort)") - delegate.handleClientRequest(clientSocket) + delegate.handleClientRequest(socket: clientSocket) } while true } catch let error as Socket.Error { diff --git a/Sources/KituraNet/IncomingMessage.swift b/Sources/KituraNet/IncomingMessage.swift index 84fea8a..ac53cd3 100644 --- a/Sources/KituraNet/IncomingMessage.swift +++ b/Sources/KituraNet/IncomingMessage.swift @@ -170,7 +170,7 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// /// - Parameter helper: the IncomingMessageHelper /// - func setup(helper: IncomingMessageHelper) { + func setup(_ helper: IncomingMessageHelper) { self.helper = helper } @@ -180,7 +180,7 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// /// - Parameter callback: (HttpParserErrorType) -> Void closure /// - func parse (callback: (HttpParserErrorType) -> Void) { + func parse (_ callback: (HttpParserErrorType) -> Void) { guard let parser = httpParser where status == .Initial else { freeHttpParser() callback(.InternalError) @@ -190,7 +190,7 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { while status == .Initial { do { ioBuffer!.length = 0 - let length = try helper!.readDataHelper(ioBuffer!) + let length = try helper!.readHelper(into: ioBuffer!) if length > 0 { let (nparsed, upgrade) = parser.execute(UnsafePointer(ioBuffer!.bytes), length: length) if upgrade == 1 { @@ -230,12 +230,12 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// - Returns: the number of bytes read /// public func read(into data: NSMutableData) throws -> Int { - var count = bodyChunk.fillData(data) + var count = bodyChunk.fill(data: data) if count == 0 { if let parser = httpParser where status == .HeadersComplete { do { ioBuffer!.length = 0 - count = try helper!.readDataHelper(ioBuffer!) + count = try helper!.readHelper(into: ioBuffer!) if count > 0 { let (nparsed, upgrade) = parser.execute(UnsafePointer(ioBuffer!.bytes), length: count) if upgrade == 1 { @@ -247,7 +247,7 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { status = .Error } else { - count = bodyChunk.fillData(data) + count = bodyChunk.fill(data: data) } } else { @@ -274,7 +274,7 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// /// - Returns: the number of bytes read /// - public func readAllData(data: NSMutableData) throws -> Int { + public func readAllData(into data: NSMutableData) throws -> Int { var length = try read(into: data) var bytesRead = length while length != 0 { @@ -319,12 +319,9 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// /// - Parameter data: the data /// - func onUrl(data: NSData) { - #if os(Linux) - url.appendData(data) - #else + func onUrl(_ data: NSData) { + url.append(data) - #endif } @@ -333,16 +330,12 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// /// - Parameter data: the data /// - func onHeaderField (data: NSData) { + func onHeaderField (_ data: NSData) { if lastHeaderWasAValue { addHeader() } - #if os(Linux) - lastHeaderField.appendData(data) - #else lastHeaderField.append(data) - #endif lastHeaderWasAValue = false } @@ -352,13 +345,9 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// /// - Parameter data: the data /// - func onHeaderValue (data: NSData) { + func onHeaderValue (_ data: NSData) { - #if os(Linux) - lastHeaderValue.appendData(data) - #else lastHeaderValue.append(data) - #endif lastHeaderWasAValue = true } @@ -374,7 +363,7 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { rawHeaders.append(headerKey) rawHeaders.append(headerValue) - headerStorage.addHeader(headerKey, headerValue: headerValue) + headerStorage.addHeader(key: headerKey, value: headerValue) lastHeaderField.length = 0 lastHeaderValue.length = 0 @@ -386,9 +375,9 @@ public class IncomingMessage : HttpParserDelegate, SocketReader { /// /// - Parameter data: the data /// - func onBody (data: NSData) { + func onBody (_ data: NSData) { - self.bodyChunk.appendData(data) + self.bodyChunk.append(data: data) } @@ -454,7 +443,7 @@ internal class HeaderStorage { // internal var arrayHeaders = [String: [String]]() - func addHeader(headerKey: String, headerValue: String) { + func addHeader(key headerKey: String, value headerValue: String) { #if os(Linux) let headerKeyLowerCase = headerKey.bridge().lowercaseString #else @@ -577,7 +566,7 @@ public class ArrayHeaders { #if os(Linux) result = entry.bridge().componentsSeparatedByString(", ") #else - result = entry.componentsSeparated(by: ", ") + result = entry.components(separatedBy: ", ") #endif } } @@ -612,7 +601,7 @@ public struct ArrayHeadersIterator: IteratorProtocol { #if os(Linux) result = (simpleKey, simpleValue.bridge().componentsSeparatedByString(", ")) #else - result = (simpleKey, simpleValue.componentsSeparated(by: ", ")) + result = (simpleKey, simpleValue.components(separatedBy: ", ")) #endif } } @@ -627,6 +616,6 @@ protocol IncomingMessageHelper: class { /// /// TODO: ??? /// - func readDataHelper(data: NSMutableData) throws -> Int + func readHelper(into data: NSMutableData) throws -> Int } diff --git a/Sources/KituraNet/ServerRequest.swift b/Sources/KituraNet/ServerRequest.swift index 37d6f24..be25fba 100644 --- a/Sources/KituraNet/ServerRequest.swift +++ b/Sources/KituraNet/ServerRequest.swift @@ -54,7 +54,7 @@ extension ServerRequest: IncomingMessageHelper { /// /// TODO: ??? /// - func readDataHelper(data: NSMutableData) throws -> Int { + func readHelper(into data: NSMutableData) throws -> Int { return try socket.read(into: data) diff --git a/Sources/KituraNet/ServerResponse.swift b/Sources/KituraNet/ServerResponse.swift index 4955a78..4326f7e 100644 --- a/Sources/KituraNet/ServerResponse.swift +++ b/Sources/KituraNet/ServerResponse.swift @@ -14,6 +14,7 @@ * limitations under the License. **/ +import KituraSys import Socket import Foundation @@ -26,27 +27,37 @@ public class ServerResponse : SocketWriter { /// Socket for the ServerResponse /// private var socket: Socket? - + /// - /// TODO: ??? + /// Size of buffer + /// + private let BUFFER_SIZE = 2000 + + /// + /// Buffer for HTTP response line, headers, and short bodies + /// + private var buffer: NSMutableData + + /// + /// Whether or not the HTTP response line and headers have been flushed. /// private var startFlushed = false - + /// /// TODO: ??? /// private var singleHeaders: [String: String] = [:] - + /// /// TODO: ??? /// private var multiHeaders: [String: [String]] = [:] - + /// /// Status code /// - public var status = HttpStatusCode.OK.rawValue - + private var status = HttpStatusCode.OK.rawValue + /// /// Status code /// @@ -60,28 +71,29 @@ public class ServerResponse : SocketWriter { } } } - + /// /// Initializes a ServerResponse instance /// init(socket: Socket) { - + self.socket = socket + buffer = NSMutableData(capacity: BUFFER_SIZE)! setHeader("Date", value: SpiUtils.httpDate()) - + } - + /// /// Get a specific headers for the response by key /// /// - Parameter key: the header key /// - public func getHeader(key: String) -> String? { - + public func getHeader(_ key: String) -> String? { + return singleHeaders[key] - + } - + /// /// Get all values on a specific key /// @@ -89,7 +101,7 @@ public class ServerResponse : SocketWriter { /// /// - Returns: a list of String values /// - public func getHeaders(key: String) -> [String]? { + public func getHeaders(_ key: String) -> [String]? { return multiHeaders[key] @@ -101,7 +113,7 @@ public class ServerResponse : SocketWriter { /// - Parameter key: key /// - Parameter value: the value /// - public func setHeader(key: String, value: String) { + public func setHeader(_ key: String, value: String) { singleHeaders[key] = value multiHeaders.removeValue(forKey: key) } @@ -112,7 +124,7 @@ public class ServerResponse : SocketWriter { /// - Parameter key: key /// - Parameter value: the value /// - public func setHeader(key: String, value: [String]) { + public func setHeader(_ key: String, value: [String]) { multiHeaders[key] = value singleHeaders.removeValue(forKey: key) } @@ -166,23 +178,23 @@ public class ServerResponse : SocketWriter { singleHeaders.removeValue(forKey: key) multiHeaders.removeValue(forKey: key) } - + /// - /// Write a string as a response + /// Write a string as a response /// /// - Parameter string: String data to be written. /// /// - Throws: ??? /// public func write(from string: String) throws { - - if let socket = socket { + + if socket != nil { try flushStart() - try socket.write(from: string) + try writeToSocketThroughBuffer(text: string) } - + } - + /// /// Write data as a response /// @@ -193,14 +205,23 @@ public class ServerResponse : SocketWriter { /// - Throws: ??? /// public func write(from data: NSData) throws { - + if let socket = socket { try flushStart() - try socket.write(from: data) + if buffer.length + data.length > BUFFER_SIZE && buffer.length != 0 { + try socket.write(from: buffer) + buffer.length = 0 + } + if data.length > BUFFER_SIZE { + try socket.write(from: data) + } + else { + buffer.append(data) + } } - + } - + /// /// End the response /// @@ -221,11 +242,14 @@ public class ServerResponse : SocketWriter { public func end() throws { if let socket = socket { try flushStart() + if buffer.length > 0 { + try socket.write(from: buffer) + } socket.close() } socket = nil } - + /// /// Begin flushing the buffer /// @@ -233,39 +257,60 @@ public class ServerResponse : SocketWriter { /// private func flushStart() throws { - guard let socket = socket where !startFlushed else { + if socket == nil || startFlushed { return } - try socket.write(from: "HTTP/1.1 ") - try socket.write(from: String(status)) - try socket.write(from: " ") + try writeToSocketThroughBuffer(text: "HTTP/1.1 ") + try writeToSocketThroughBuffer(text: String(status)) + try writeToSocketThroughBuffer(text: " ") var statusText = Http.statusCodes[status] if statusText == nil { statusText = "" } - try socket.write(from: statusText!) - try socket.write(from: "\r\n") + try writeToSocketThroughBuffer(text: statusText!) + try writeToSocketThroughBuffer(text: "\r\n") for (key, value) in singleHeaders { - try socket.write(from: key) - try socket.write(from: ": ") - try socket.write(from: value) - try socket.write(from: "\r\n") + try writeToSocketThroughBuffer(text: key) + try writeToSocketThroughBuffer(text: ": ") + try writeToSocketThroughBuffer(text: value) + try writeToSocketThroughBuffer(text: "\r\n") } for (key, valueSet) in multiHeaders { for value in valueSet { - try socket.write(from: key) - try socket.write(from: ": ") - try socket.write(from: value) - try socket.write(from: "\r\n") + try writeToSocketThroughBuffer(text: key) + try writeToSocketThroughBuffer(text: ": ") + try writeToSocketThroughBuffer(text: value) + try writeToSocketThroughBuffer(text: "\r\n") } } - try socket.write(from: "\r\n") + try writeToSocketThroughBuffer(text: "\r\n") startFlushed = true } + + /// + /// Function to write Strings to the socket through the buffer + /// + private func writeToSocketThroughBuffer(text: String) throws { + guard let socket = socket, + let utf8Data = StringUtils.toUtf8String(text) else { + return + } + + if buffer.length + utf8Data.length > BUFFER_SIZE && buffer.length != 0 { + try socket.write(from: buffer) + buffer.length = 0 + } + if utf8Data.length > BUFFER_SIZE { + try socket.write(from: utf8Data) + } + else { + buffer.append(utf8Data) + } + } } diff --git a/Sources/KituraNet/SpiUtils.swift b/Sources/KituraNet/SpiUtils.swift index 7d4817a..a3f21ad 100644 --- a/Sources/KituraNet/SpiUtils.swift +++ b/Sources/KituraNet/SpiUtils.swift @@ -66,7 +66,7 @@ public class SpiUtils { /// /// - Returns: string representation of timestamp /// - public static func httpDate(date: NSDate) -> String { + public static func httpDate(_ date: NSDate) -> String { #if os(Linux) let calendar = NSCalendar.currentCalendar() @@ -97,7 +97,7 @@ public class SpiUtils { /// /// - Parameter num: the number /// - private static func twoDigit(num: Int) -> String { + private static func twoDigit(_ num: Int) -> String { return (num < 10 ? "0" : "") + String(num) diff --git a/Tests/KituraNet/ParserTests.swift b/Tests/KituraNet/ParserTests.swift index 137a4d8..2f2394e 100644 --- a/Tests/KituraNet/ParserTests.swift +++ b/Tests/KituraNet/ParserTests.swift @@ -31,7 +31,7 @@ class ParserTests: XCTestCase { #if os(Linux) let url = "https://example.org/absolute/URI/with/absolute/path/to/resource.txt".bridge().dataUsingEncoding(NSUTF8StringEncoding)! #else - let url = "https://example.org/absolute/URI/with/absolute/path/to/resource.txt".data(usingEncoding: NSUTF8StringEncoding)! + let url = "https://example.org/absolute/URI/with/absolute/path/to/resource.txt".data(using: NSUTF8StringEncoding)! #endif let urlParser = UrlParser(url: url, isConnect: false) XCTAssertEqual(urlParser.schema!, "https", "Incorrect schema") @@ -43,7 +43,7 @@ class ParserTests: XCTestCase { #if os(Linux) let url = "abc://username:password@example.com:123/path/data?key=value&key1=value1#fragid1".bridge().dataUsingEncoding(NSUTF8StringEncoding)! #else - let url = "abc://username:password@example.com:123/path/data?key=value&key1=value1#fragid1".data(usingEncoding: NSUTF8StringEncoding)! + let url = "abc://username:password@example.com:123/path/data?key=value&key1=value1#fragid1".data(using: NSUTF8StringEncoding)! #endif let urlParser = UrlParser(url: url, isConnect: false) XCTAssertEqual(urlParser.schema!, "abc", "Incorrect schema")