0001    //
0002    //  HttpRequest.swift
0003    //  Swifter
0004    //
0005    //  Copyright (c) 2014-2016 Damian KoĊ‚akowski. All rights reserved.
0006    //
0007    
0008    import Foundation
0009    
0010    public class HttpRequest
HttpHandlers+Files.swift:12
    public class func shareFilesFromDirectory(directoryPath: String) -> (HttpRequest -> HttpResponse) {
HttpHandlers+Files.swift:33
    public class func directory(dir: String) -> (HttpRequest -> HttpResponse) {
HttpHandlers+Files.swift:95
    public class func directoryBrowser(dir: String) -> (HttpRequest -> HttpResponse) {
HttpHandlers+WebSockets.swift:14
        _ binary: ((WebSocketSession, [UInt8]) -> Void)?) -> (HttpRequest -> HttpResponse) {
HttpParser.swift:22
    public func readHttpRequest(socket: Socket) throws -> HttpRequest {
HttpParser.swift:28
        let request = HttpRequest()
HttpRequest.swift:129
            if value > HttpRequest.CR {
HttpRequest.swift:132
            if value == HttpRequest.NL {
HttpRequest.swift:151
                if body.last == HttpRequest.NL {
HttpRequest.swift:153
                    if body.last == HttpRequest.CR {
HttpRouter.swift:14
        var handler: (HttpRequest -> HttpResponse)? = nil
HttpRouter.swift:38
    public func register(method: String?, path: String, handler: (HttpRequest -> HttpResponse)?) {
HttpRouter.swift:49
    public func route(method: String?, path: String) -> ([String: String], HttpRequest -> HttpResponse)? {
HttpRouter.swift:79
    private func findHandler(inout node: Node, inout params: [String: String], inout generator: IndexingGenerator<[String]>) -> (HttpRequest -> HttpResponse)? {
HttpServer.swift:46
    override public func dispatch(method: String, path: String) -> ([String:String], HttpRequest -> HttpResponse) {
HttpServerIO.swift:50
    public func dispatch(method: String, path: String) -> ([String: String], HttpRequest -> HttpResponse) {
{ 0011 0012 public var path
DemoServer.swift:33
    server["/magic"] = { .OK(.Html("You asked for " + $0.path)) }
DemoServer.swift:48
        return .OK(.Html("<h3>Address: \(r.address)</h3><h3>Url:</h3> \(r.path)<h3>Method:</h3>\(r.method)<h3>Headers:</h3>\(headersInfo)<h3>Query:</h3>\(queryParamsInfo)<h3>Path params:</h3>\(pathParamsInfo)"))
DemoServer.swift:106
        return .OK(.Html(r.path))
HttpHandlers+Files.swift:110
                    response += files.map({ "<tr><td><a href=\"\(r.path)/\($0)\">\($0)</a></td></tr>"}).joinWithSeparator("")
HttpParser.swift:30
        request.path = statusLineTokens[1]
HttpParser.swift:31
        request.queryParams = extractQueryParams(request.path)
HttpServerIO.swift:59
            let (params, handler) = self.dispatch(request.method, path: request.path)
: String = "" 0013 public var queryParams
DemoServer.swift:41
        for (name, value) in r.queryParams {
HttpParser.swift:31
        request.queryParams = extractQueryParams(request.path)
: [(String, String)] = [] 0014 public var method
DemoServer.swift:48
        return .OK(.Html("<h3>Address: \(r.address)</h3><h3>Url:</h3> \(r.path)<h3>Method:</h3>\(r.method)<h3>Headers:</h3>\(headersInfo)<h3>Query:</h3>\(queryParamsInfo)<h3>Path params:</h3>\(pathParamsInfo)"))
HttpParser.swift:29
        request.method = statusLineTokens[0]
HttpServerIO.swift:59
            let (params, handler) = self.dispatch(request.method, path: request.path)
: String = "" 0015 public var headers
DemoServer.swift:37
        for (name, value) in r.headers {
HttpHandlers+Files.swift:46
            if let rangeHeader = r.headers["range"] {
HttpHandlers+Files.swift:49
                    return .BadRequest(.Text("Invalid value of 'Range' header: \(r.headers["range"])"))
HttpHandlers+Files.swift:61
                    return .BadRequest(.Text("Invalid value of 'Range' header: \(r.headers["range"])"))
HttpHandlers+WebSockets.swift:17
                return .BadRequest(.Text("Invalid value of 'Upgrade' header: \(r.headers["upgrade"])"))
HttpHandlers+WebSockets.swift:20
                return .BadRequest(.Text("Invalid value of 'Connection' header: \(r.headers["connection"])"))
HttpHandlers+WebSockets.swift:22
            guard let secWebSocketKey = r.headers["sec-websocket-key"] else {
HttpHandlers+WebSockets.swift:23
                return .BadRequest(.Text("Invalid value of 'Sec-Websocket-Key' header: \(r.headers["sec-websocket-key"])"))
HttpParser.swift:32
        request.headers = try readHeaders(socket)
HttpParser.swift:33
        if let contentLength = request.headers["content-length"], let contentLengthValue = Int(contentLength) {
HttpRequest.swift:21
        guard let headerValue = headers[headerName] else {
HttpRequest.swift:28
        guard let contentTypeHeader = headers["content-type"] else {
HttpRequest.swift:76
        guard let contentTypeHeader = headers["content-type"] else {
HttpServerIO.swift:63
            var keepConnection = parser.supportsKeepAlive(request.headers)
: [String: String] = [:] 0016 public var body
HttpParser.swift:34
            request.body = try readBody(socket, size: contentLengthValue)
HttpRequest.swift:35
        return String.fromUInt8(body).split("&").map { param -> (String, String) in
HttpRequest.swift:91
            return parseMultiPartFormData(body, boundary: "--\(boundary)")
: [UInt8] = [] 0017 public var address
DemoServer.swift:48
        return .OK(.Html("<h3>Address: \(r.address)</h3><h3>Url:</h3> \(r.path)<h3>Method:</h3>\(r.method)<h3>Headers:</h3>\(headersInfo)<h3>Query:</h3>\(queryParamsInfo)<h3>Path params:</h3>\(pathParamsInfo)"))
HttpServerIO.swift:60
            request.address = address
: String? = "" 0018 public var params
DemoServer.swift:45
        for token in r.params {
HttpHandlers+Files.swift:14
            guard let fileRelativePath = r.params.first else {
HttpHandlers+Files.swift:36
            guard let localPath = r.params.first else {
HttpHandlers+Files.swift:97
            guard let (_, value) = r.params.first else {
HttpServerIO.swift:61
            request.params = params;
: [String: String] = [:] 0019 0020 public func hasTokenForHeader
HttpHandlers+WebSockets.swift:16
            guard r.hasTokenForHeader("upgrade", token: "websocket") else {
HttpHandlers+WebSockets.swift:19
            guard r.hasTokenForHeader("connection", token: "upgrade") else {
(headerName: String, token: String) -> Bool { 0021 guard let headerValue = headers[headerName] else { 0022 return false 0023 } 0024 return headerValue.split(",").filter({ $0.trim().lowercaseString == token }).count > 0 0025 } 0026 0027 public func parseUrlencodedForm
DemoServer.swift:78
        let formFields = r.parseUrlencodedForm()
() -> [(String, String)] { 0028 guard let contentTypeHeader = headers["content-type"] else { 0029 return [] 0030 } 0031 let contentTypeHeaderTokens = contentTypeHeader.split(";").map { $0.trim() } 0032 guard let contentType = contentTypeHeaderTokens.first where contentType == "application/x-www-form-urlencoded" else { 0033 return [] 0034 } 0035 return String.fromUInt8(body).split("&").map { param -> (String, String) in 0036 let tokens = param.split("=") 0037 if let name = tokens.first, value = tokens.last where tokens.count == 2 { 0038 return (name.replace("+", " ").removePercentEncoding(), 0039 value.replace("+", " ").removePercentEncoding()) 0040 } 0041 return ("","") 0042 } 0043 } 0044 0045 public struct MultiPart
HttpRequest.swift:75
    public func parseMultiPartFormData() -> [MultiPart] {
HttpRequest.swift:96
    private func parseMultiPartFormData(data: [UInt8], boundary: String) -> [MultiPart] {
HttpRequest.swift:98
        var result = [MultiPart]()
HttpRequest.swift:105
    private func nextMultiPart(inout generator: IndexingGenerator<[UInt8]>, boundary: String, isFirst: Bool) -> MultiPart? {
HttpRequest.swift:123
        return MultiPart(headers: headers, body: body)
{ 0046 0047 public let headers
HttpRequest.swift:59
            return headers.reduce([String]()) { (combined, header: (key: String, value: String)) -> [String] in
: [String: String] 0048 public let body
DemoServer.swift:63
            response += "Name: \(multipart.name) File name: \(multipart.fileName) Size: \(multipart.body.count)<br>"
: [UInt8] 0049 0050 public var name
DemoServer.swift:63
            response += "Name: \(multipart.name) File name: \(multipart.fileName) Size: \(multipart.body.count)<br>"
: String? { 0051 return valueFor("content-disposition", parameter: "name")?.unquote() 0052 } 0053 0054 public var fileName
DemoServer.swift:63
            response += "Name: \(multipart.name) File name: \(multipart.fileName) Size: \(multipart.body.count)<br>"
: String? { 0055 return valueFor("content-disposition", parameter: "filename")?.unquote() 0056 } 0057 0058 private func valueFor
HttpRequest.swift:51
            return valueFor("content-disposition", parameter: "name")?.unquote()
HttpRequest.swift:55
            return valueFor("content-disposition", parameter: "filename")?.unquote()
(headerName: String, parameter: String) -> String? { 0059 return headers.reduce([String]()) { (combined, header: (key: String, value: String)) -> [String] in 0060 guard header.key == headerName else { 0061 return combined 0062 } 0063 let headerValueParams = header.value.split(";").map { $0.trim() } 0064 return headerValueParams.reduce(combined, combine: { (results, token) -> [String] in 0065 let parameterTokens = token.split(1, separator: "=") 0066 if parameterTokens.first == parameter, let value = parameterTokens.last { 0067 return results + [value] 0068 } 0069 return results 0070 }) 0071 }.first 0072 } 0073 } 0074 0075 public func parseMultiPartFormData
DemoServer.swift:62
        for multipart in r.parseMultiPartFormData() {
() -> [MultiPart] { 0076 guard let contentTypeHeader = headers["content-type"] else { 0077 return [] 0078 } 0079 let contentTypeHeaderTokens = contentTypeHeader.split(";").map { $0.trim() } 0080 guard let contentType = contentTypeHeaderTokens.first where contentType == "multipart/form-data" else { 0081 return [] 0082 } 0083 var boundary: String? = nil 0084 contentTypeHeaderTokens.forEach({ 0085 let tokens = $0.split("=") 0086 if let key = tokens.first where key == "boundary" && tokens.count == 2 { 0087 boundary = tokens.last 0088 } 0089 }) 0090 if let boundary = boundary where boundary.utf8.count > 0 { 0091 return parseMultiPartFormData(body, boundary: "--\(boundary)") 0092 } 0093 return [] 0094 } 0095 0096 private func parseMultiPartFormData
HttpRequest.swift:91
            return parseMultiPartFormData(body, boundary: "--\(boundary)")
(data: [UInt8], boundary: String) -> [MultiPart] { 0097 var generator = data.generate() 0098 var result = [MultiPart]() 0099 while let part = nextMultiPart(&generator, boundary: boundary, isFirst: result.isEmpty) { 0100 result.append(part) 0101 } 0102 return result 0103 } 0104 0105 private func nextMultiPart
HttpRequest.swift:99
        while let part = nextMultiPart(&generator, boundary: boundary, isFirst: result.isEmpty) {
(inout generator: IndexingGenerator<[UInt8]>, boundary: String, isFirst: Bool) -> MultiPart? { 0106 if isFirst { 0107 guard nextMultiPartLine(&generator) == boundary else { 0108 return nil 0109 } 0110 } else { 0111 nextMultiPartLine(&generator) 0112 } 0113 var headers = [String: String]() 0114 while let line = nextMultiPartLine(&generator) where !line.isEmpty { 0115 let tokens = line.split(":") 0116 if let name = tokens.first, value = tokens.last where tokens.count == 2 { 0117 headers[name.lowercaseString] = value.trim() 0118 } 0119 } 0120 guard let body = nextMultiPartBody(&generator, boundary: boundary) else { 0121 return nil 0122 } 0123 return MultiPart(headers: headers, body: body) 0124 } 0125 0126 private func nextMultiPartLine
HttpRequest.swift:107
            guard nextMultiPartLine(&generator) == boundary else {
HttpRequest.swift:111
            nextMultiPartLine(&generator)
HttpRequest.swift:114
        while let line = nextMultiPartLine(&generator) where !line.isEmpty {
(inout generator: IndexingGenerator<[UInt8]>) -> String? { 0127 var result = String() 0128 while let value = generator.next() { 0129 if value > HttpRequest.CR { 0130 result.append(Character(UnicodeScalar(value))) 0131 } 0132 if value == HttpRequest.NL { 0133 break 0134 } 0135 } 0136 return result 0137 } 0138 0139 static let CR
HttpRequest.swift:129
            if value > HttpRequest.CR {
HttpRequest.swift:153
                    if body.last == HttpRequest.CR {
= UInt8(13) 0140 static let NL
HttpRequest.swift:132
            if value == HttpRequest.NL {
HttpRequest.swift:151
                if body.last == HttpRequest.NL {
= UInt8(10) 0141 0142 private func nextMultiPartBody
HttpRequest.swift:120
        guard let body = nextMultiPartBody(&generator, boundary: boundary) else {
(inout generator: IndexingGenerator<[UInt8]>, boundary: String) -> [UInt8]? { 0143 var body = [UInt8]() 0144 let boundaryArray = [UInt8](boundary.utf8) 0145 var matchOffset = 0; 0146 while let x = generator.next() { 0147 matchOffset = ( x == boundaryArray[matchOffset] ? matchOffset + 1 : 0 ) 0148 body.append(x) 0149 if matchOffset == boundaryArray.count { 0150 body.removeRange(Range<Int>(body.count-matchOffset ..< body.count)) 0151 if body.last == HttpRequest.NL { 0152 body.removeLast() 0153 if body.last == HttpRequest.CR { 0154 body.removeLast() 0155 } 0156 } 0157 return body 0158 } 0159 } 0160 return nil 0161 } 0162 } 0163