Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
dfirsht committed Jun 2, 2016
2 parents 1f0f012 + 6193ca8 commit 2cf242f
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 66 deletions.
6 changes: 3 additions & 3 deletions Sources/KituraNet/ClientResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ extension ClientResponse: IncomingMessageHelper {
/// - Returns: ???
///
func readHelper(into data: NSMutableData) -> Int {
return responseBuffers.fill(data: data)


let length = responseBuffers.fill(data: data)
return length > 0 ? length : -1
}

}
48 changes: 24 additions & 24 deletions Sources/KituraNet/HTTP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import Foundation
// MARK: HTTP

public class HTTP {

///
/// Mapping of integer status codes to the String description
///
public static let statusCodes = [

100: "Continue", 101: "Switching Protocols", 102: "Processing",
200: "OK", 201: "Created", 202: "Accepted", 203: "Non Authoritative Information",
204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status",
Expand All @@ -42,18 +42,18 @@ public class HTTP {
504: "Gateway Timeout", 505: "HTTP Version Not Supported", 507: "Insufficient Storage",
511: "Network Authentication Required"
]

///
/// Creates a new HTTP server
///
///
/// - Returns: an instance of HTTPServer
///
public static func createServer() -> HTTPServer {

return HTTPServer()

}

///
/// Creates a new ClientRequest using URL
///
Expand All @@ -63,11 +63,11 @@ public class HTTP {
/// - Returns: a ClientRequest instance
///
public static func request(_ url: String, callback: ClientRequestCallback) -> ClientRequest {

return ClientRequest(url: url, callback: callback)

}

///
/// Creates a new ClientRequest using a list of options
///
Expand All @@ -77,45 +77,45 @@ public class HTTP {
/// - Returns: a ClientRequest instance
///
public static func request(_ options: [ClientRequestOptions], callback: ClientRequestCallback) -> ClientRequest {

return ClientRequest(options: options, callback: callback)

}

///
/// Creates a new ClientRequest using URL
/// *Note*: This method will end the ClientRequest immediately after creation
///
/// - Parameter url: URL address for the request
/// - Parameter callback: closure to run after the request
/// - Parameter callback: closure to run after the request
///
/// - Returns: a ClientRequest instance
///
public static func get(_ url: String, callback: ClientRequestCallback) -> ClientRequest {

let req = ClientRequest(url: url, callback: callback)
req.end()
return req

}

///
/// A set of characters that are valid in requests
///
#if os(Linux)
private static let allowedCharacterSet = NSCharacterSet(charactersIn:"\"#%/<>?@\\^`{|}").invertedSet
private static let allowedCharacterSet = NSCharacterSet(charactersIn:"\"#%/<>?@\\^`{|} ").invertedSet
#else
private static let allowedCharacterSet = NSCharacterSet(charactersIn:"\"#%/<>?@\\^`{|}").inverted
private static let allowedCharacterSet = NSCharacterSet(charactersIn:"\"#%/<>?@\\^`{|} ").inverted
#endif

///
/// Transform the URL into escaped characters
///
///
/// *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 {

#if os(Linux)
if let escaped = url.bridge().stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) {
return escaped
Expand All @@ -125,7 +125,7 @@ public class HTTP {
return escaped
}
#endif

return url
}
}
Expand All @@ -135,7 +135,7 @@ public class HTTP {
/// HTTP status codes and numbers
///
public enum HTTPStatusCode: Int {

case accepted = 202, badGateway = 502, badRequest = 400, conflict = 409, `continue` = 100, created = 201
case expectationFailed = 417, failedDependency = 424, forbidden = 403, gatewayTimeout = 504, gone = 410
case httpVersionNotSupported = 505, insufficientSpaceOnResource = 419, insufficientStorage = 507
Expand All @@ -149,5 +149,5 @@ public enum HTTPStatusCode: Int {
case resetContent = 205, seeOther = 303, serviceUnavailable = 503, switchingProtocols = 101
case temporaryRedirect = 307, tooManyRequests = 429, unauthorized = 401, unprocessableEntity = 422
case unsupportedMediaType = 415, useProxy = 305, unknown = -1

}
26 changes: 17 additions & 9 deletions Sources/KituraNet/HTTPParser/HTTPParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ class HTTPParser {
/// - Returns: an HTTPParser instance
///
init(isRequest: Bool) {
self.isRequest = isRequest

self.isRequest = isRequest

parser = http_parser()
settings = http_parser_settings()

Expand All @@ -95,9 +95,10 @@ class HTTPParser {

settings.on_body = { (parser, chunk, length) -> Int32 in
let p = UnsafePointer<HTTPParserDelegate?>(parser.pointee.data)
let data = NSData(bytes: chunk, length: length)
p?.pointee?.onBody(data)

if p?.pointee?.saveBody == true {
let data = NSData(bytes: chunk, length: length)
p?.pointee?.onBody(data)
}
return 0
}

Expand Down Expand Up @@ -160,20 +161,27 @@ class HTTPParser {
func reset() {
http_parser_init(&parser, isRequest ? HTTP_REQUEST : HTTP_RESPONSE)
}

///
/// Did the request include a Connection: keep-alive header?
///
func isKeepAlive() -> Bool {
return isRequest && http_should_keep_alive(&parser) == 1
}

}

///
/// Delegate protocol for HTTP parsing stages
///
protocol HTTPParserDelegate: class {

var saveBody : Bool { get }
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 reset()

func reset()
}
9 changes: 4 additions & 5 deletions Sources/KituraNet/HTTPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,22 +139,21 @@ extension HTTPServer : HTTPServerSPIDelegate {
///
/// - Parameter clientSocket: the socket used for connecting
///
func handleClientRequest(socket clientSocket: Socket) {
func handleClientRequest(socket clientSocket: Socket, fromKeepAlive: Bool) {

guard let delegate = delegate else {
return
}

HTTPServer.clientHandlerQueue.queueAsync() {

let response = ServerResponse(socket: clientSocket)
let request = ServerRequest(socket: clientSocket)
let response = ServerResponse(socket: clientSocket, request: request)
request.parse() { status in
switch status {
case .success:
delegate.handle(request: request, response: response)
case .parsedLessThanRead:
print("ParsedLessThanRead")
response.statusCode = .badRequest
do {
try response.end()
Expand All @@ -163,9 +162,9 @@ extension HTTPServer : HTTPServerSPIDelegate {
// handle error in connection
}
case .unexpectedEOF:
print("UnexpectedEOF")
break
case .internalError:
print("InternalError")
break
}
}

Expand Down
7 changes: 4 additions & 3 deletions Sources/KituraNet/HTTPServerSPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class HTTPServerSPI {
let clientSocket = try socket.acceptClientConnection()
Log.info("Accepted connection from: " +
"\(clientSocket.remoteHostname):\(clientSocket.remotePort)")
delegate.handleClientRequest(socket: clientSocket)
delegate.handleClientRequest(socket: clientSocket, fromKeepAlive: false)
} while true
} catch let error as Socket.Error {

Expand All @@ -78,7 +78,8 @@ protocol HTTPServerSPIDelegate: class {
/// Handle the client request
///
/// - Parameter socket: the socket
/// - Parameter fromKeepAlive - Was this from a socket being kept alive
///
func handleClientRequest(socket: Socket)
func handleClientRequest(socket: Socket, fromKeepAlive: Bool)

}
51 changes: 43 additions & 8 deletions Sources/KituraNet/IncomingMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,27 +64,27 @@ public class IncomingMessage : HTTPParserDelegate, SocketReader {
// TODO: trailers

///
/// TODO: ???
/// State of callbacks from parser WRT headers
///
private var lastHeaderWasAValue = false

///
/// TODO: ???
/// Bytes of a header key that was just parsed and returned in chunks by the pars
///
private var lastHeaderField = NSMutableData()

///
/// TODO: ???
/// Bytes of a header value that was just parsed and returned in chunks by the parser
///
private var lastHeaderValue = NSMutableData()

///
/// TODO: ???
/// The http_parser Swift wrapper
///
private var httpParser: HTTPParser?

///
/// TODO: ???
/// State of incoming message handling
///
private var status = Status.initial

Expand All @@ -94,7 +94,7 @@ public class IncomingMessage : HTTPParserDelegate, SocketReader {
private var bodyChunk = BufferList()

///
/// TODO: ???
/// Reader helper, reads from underlying data source
///
private weak var helper: IncomingMessageHelper?

Expand All @@ -108,7 +108,11 @@ public class IncomingMessage : HTTPParserDelegate, SocketReader {
///
private var buffer = NSMutableData(capacity: IncomingMessage.bufferSize)


///
/// Indicates if the parser should save the message body and call onBody()
///
var saveBody = true

///
/// List of status states
///
Expand Down Expand Up @@ -276,13 +280,44 @@ public class IncomingMessage : HTTPParserDelegate, SocketReader {
public func readAllData(into data: NSMutableData) throws -> Int {
var length = try read(into: data)
var bytesRead = length
while length != 0 {
while length > 0 {
length = try read(into: data)
bytesRead += length
}
return bytesRead
}


///
/// Read message body without storing it anywhere
///
func drain() {
if let parser = httpParser {
saveBody = false
while status == .headersComplete {
do {
ioBuffer!.length = 0
let count = try helper!.readHelper(into: ioBuffer!)
if count > 0 {
let (nparsed, _) = parser.execute(UnsafePointer<Int8>(ioBuffer!.bytes), length: count)
if (nparsed != count) {
freeHTTPParser()
status = .error
}
}
else {
status = .messageComplete
freeHTTPParser()
}
}
catch {
freeHTTPParser()
status = .error
}
}
}
}

///
/// Read the string
///
Expand Down
6 changes: 3 additions & 3 deletions Sources/KituraNet/ServerRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ extension ServerRequest: IncomingMessageHelper {
/// TODO: ???
///
func readHelper(into data: NSMutableData) throws -> Int {
return try socket.read(into: data)


let length = try socket.read(into: data)
return length > 0 ? length : (socket.isConnected ? 0 : -1)
}

}
Loading

0 comments on commit 2cf242f

Please sign in to comment.