Răsfoiți Sursa

Merge branch 'master' of https://github.com/glock45/swifter

Conflicts:
	Swifter/AppDelegate.swift
pyanfield 11 ani în urmă
părinte
comite
9db1daa0bb

+ 52 - 0
Common/ActiveRecord/ActiveRecord.swift

@@ -0,0 +1,52 @@
+//
+//  ActiveRecord.swift
+//  Swifter
+//
+//  Created by Damian Kolakowski on 13/11/14.
+//  Copyright (c) 2014 Damian Kołakowski. All rights reserved.
+//
+
+import Foundation
+
+struct SwifterActiveRecordField {
+    let name: String?
+}
+
+class SwifterActiveRecord /* Probbaly we will use generics and not follow Ruby's approach based on subclassing. Methods like find() and get() need to return a correct types. */ {
+    
+    init() {
+        let properties = listProperties()
+        // TODO migrate properties scheme to DB scheme.
+    }
+    
+    private func listProperties() -> [SwifterActiveRecordField]? {
+        // Extract public properties so we will know
+        var results = [SwifterActiveRecordField]()
+        let classInfoDump = reflect(self)
+        for var index = 1; index < classInfoDump.count; ++index {
+            let field = classInfoDump[index]
+            results.append(SwifterActiveRecordField(name: field.0))
+            print("\(field.1.valueType)")
+        }
+        return results
+    }
+    
+    //func findBy(
+    
+    func all() -> Array<String> {
+        return []
+    }
+    
+    func commit(error: NSErrorPointer) -> Bool {
+        //TODO commit changes to DB.
+        return false
+    }
+}
+
+// An example model class.
+
+class Person: SwifterActiveRecord {
+    var firstName: String?
+    var lastName: String?
+    var age: UInt?
+}

+ 57 - 0
Common/DemoServer.swift

@@ -0,0 +1,57 @@
+//
+//  DemoServer.swift
+//  Swifter
+//
+//  Created by Damian Kolakowski on 14/11/14.
+//  Copyright (c) 2014 Damian Kołakowski. All rights reserved.
+//
+
+import Foundation
+
+func demoServer(publicDir: String?) -> HttpServer {
+    let server = HttpServer()
+    if let publicDir = publicDir {
+        server["/resources/(.+)"] = HttpHandlers.directory(publicDir)
+    }
+    server["/test"] = { request in
+        var headersInfo = ""
+        for (name, value) in request.headers {
+            headersInfo += "\(name) : \(value)<br>"
+        }
+        let response = "<html><body>Url: \(request.url)<br>Method: \(request.method)<br>\(headersInfo)</body></html>"
+        return .OK(.RAW(response))
+    }
+    server["/params/(.+)/(.+)"] = { request in
+        var capturedGroupsIngo = ""
+        for (index, group) in enumerate(request.capturedUrlGroups) {
+            capturedGroupsIngo += "Expression group \(index) : \(group)<br>"
+        }
+        let response = "<html><body>Url: \(request.url)<br>Method: \(request.method)<br>\(capturedGroupsIngo)</body></html>"
+        return .OK(.RAW(response))
+    }
+    server["/json"] = { request in
+        return .OK(.JSON(["posts" : [[ "id" : 1, "message" : "hello world"],[ "id" : 2, "message" : "sample message"]], "new_updates" : false]))
+    }
+    server["/redirect"] = { request in
+        return .MovedPermanently("http://www.google.com")
+    }
+    server["/long"] = { request in
+        var longResponse = ""
+        for k in 0..<1000 { longResponse += "(\(k)),->" }
+        return .OK(.RAW(longResponse))
+    }
+    server["/demo"] = { request in
+        return .OK(.RAW("<html><body><center><h2>Hello Swift</h2>" +
+            "<img src=\"https://devimages.apple.com.edgekey.net/swift/images/swift-hero_2x.png\"/><br>" +
+            "</center></body></html>"))
+    }
+    server["/"] = { request in
+        var listPage = "<html><body>Available services:<br><ul>"
+        for item in server.routes() {
+            listPage += "<li><a href=\"\(item)\">\(item)</a></li>"
+        }
+        listPage += "</ul></body></html>"
+        return .OK(.RAW(listPage))
+    }
+    return server
+}

+ 24 - 0
Common/HttpHandlers.swift

@@ -0,0 +1,24 @@
+//
+//  Handlers.swift
+//  Swifter
+//
+//  Created by Damian Kolakowski on 14/11/14.
+//  Copyright (c) 2014 Damian Kołakowski. All rights reserved.
+//
+
+import Foundation
+
+class HttpHandlers {
+
+    class func directory(dir: String) -> ( HttpRequest -> HttpResponse ) {
+        return { request in
+            if let localPath = request.capturedUrlGroups.first {
+                let filesPath = dir.stringByExpandingTildeInPath.stringByAppendingPathComponent(localPath)
+                if let fileBody = String(contentsOfFile: filesPath, encoding: NSUTF8StringEncoding, error: nil) {
+                    return HttpResponse.OK(.RAW(fileBody))
+                }
+            }
+            return HttpResponse.NotFound
+        }
+    }
+}

+ 12 - 13
Common/HttpParser.swift

@@ -10,10 +10,10 @@ import Foundation
 class HttpParser {
     
     class func err(reason:String) -> NSError {
-        return NSError.errorWithDomain("HTTP_PARSER", code: 0, userInfo:[NSLocalizedFailureReasonErrorKey : reason])
+        return NSError(domain: "HTTP_PARSER", code: 0, userInfo:[NSLocalizedFailureReasonErrorKey : reason])
     }
 
-    func nextHttpRequest(socket: CInt, error:NSErrorPointer = nil) -> HttpRequest? { //(String, String, Dictionary<String, String>)? {
+    func nextHttpRequest(socket: CInt, error:NSErrorPointer = nil) -> HttpRequest? {
         if let statusLine = nextLine(socket, error: error) {
             let statusTokens = split(statusLine, { $0 == " " })
             println(statusTokens)
@@ -24,23 +24,22 @@ class HttpParser {
             let method = statusTokens[0]
             let path = statusTokens[1]
             if let headers = nextHeaders(socket, error: error) {
-                var responseString = ""
-                while let line = nextLine(socket, error: error)
-                {
+                var requestBody = ""
+                while let line = nextLine(socket, error: error) {
                     if line.isEmpty {
                         break
                     }
-                    responseString += line
+                    requestBody += line
                 }
-                println(responseString)
-                let responseData = responseString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
-                return HttpRequest(url: path, method: method, headers: headers, responseData: responseData)
+                println(requestBody)
+                let body = requestBody.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
+                return HttpRequest(url: path, method: method, headers: headers, body: body, capturedUrlGroups: [])
             }
         }
         return nil
     }
     
-    func nextHeaders(socket: CInt, error:NSErrorPointer) -> Dictionary<String, String>? {
+    private func nextHeaders(socket: CInt, error:NSErrorPointer) -> Dictionary<String, String>? {
         var headers = Dictionary<String, String>()
         while let headerLine = nextLine(socket, error: error) {
             if ( headerLine.isEmpty ) {
@@ -65,10 +64,10 @@ class HttpParser {
     var recvBufferSize: Int = 0
     var recvBufferOffset: Int = 0
     
-    func nextUInt8(socket: CInt) -> Int {
+    private func nextUInt8(socket: CInt) -> Int {
         if ( recvBufferSize == 0 || recvBufferOffset == recvBuffer.count ) {
             recvBufferOffset = 0
-            recvBufferSize = recv(socket, &recvBuffer, UInt(recvBuffer.count), MSG_DONTWAIT)
+            recvBufferSize = recv(socket, &recvBuffer, UInt(recvBuffer.count), 0)
             if ( recvBufferSize <= 0 ) { return recvBufferSize }
             if recvBufferSize < recvBuffer.count
             {
@@ -80,7 +79,7 @@ class HttpParser {
         return Int(returnValue)
     }
     
-    func nextLine(socket: CInt, error:NSErrorPointer) -> String? {
+    private func nextLine(socket: CInt, error:NSErrorPointer) -> String? {
         var characters: String = ""
         var n = 0
         do {

+ 2 - 1
Common/HttpRequest.swift

@@ -12,5 +12,6 @@ struct HttpRequest {
     let url: String
     let method: String
     let headers: Dictionary<String, String>
-	let responseData: NSData?
+	let body: NSData?
+    var capturedUrlGroups: [String]
 }

+ 47 - 28
Common/HttpServer.swift

@@ -19,16 +19,10 @@ class HttpServer
     
     subscript (path: String) -> Handler? {
         get {
-            for (expression, handler) in handlers {
-                let numberOfMatches: Int = expression.numberOfMatchesInString(path, options: matchingOptions, range: NSMakeRange(0, path.lengthOfBytesUsingEncoding(NSASCIIStringEncoding)))
-                if ( numberOfMatches > 0 ) {
-                    return handler
-                }
-            }
             return nil
         }
         set ( newValue ) {
-            if let regex: NSRegularExpression = NSRegularExpression.regularExpressionWithPattern(path, options: expressionOptions, error: nil) {
+            if let regex: NSRegularExpression = NSRegularExpression(pattern: path, options: expressionOptions, error: nil) {
                 if let newHandler = newValue {
                     handlers.append(expression: regex, handler: newHandler)
                 }
@@ -36,25 +30,31 @@ class HttpServer
         }
     }
     
-    subscript (path: String) -> String {
-        get {
-            return path
-        }
-        set ( directoryPath ) {
-            if let regex = NSRegularExpression.regularExpressionWithPattern(path, options: expressionOptions, error: nil) {
-                handlers.append(expression: regex, handler: { request in
-                    let result = regex.firstMatchInString(request.url, options: self.matchingOptions, range: NSMakeRange(0, request.url.lengthOfBytesUsingEncoding(NSASCIIStringEncoding)))
-                    let nsPath: NSString = request.url
-                    let filesPath = directoryPath.stringByExpandingTildeInPath
-                        .stringByAppendingPathComponent(nsPath.substringWithRange(result!.rangeAtIndex(1)))
-                    if let fileBody = String.stringWithContentsOfFile(filesPath, encoding: NSASCIIStringEncoding, error: nil) {
-                        return HttpResponse.OK(.RAW(fileBody))
-                    }
-                    return HttpResponse.NotFound
-                })
-            }
-        }
-    }
+//    Uncommenting this will cause following compilation errors:
+//
+//      Cannot invoke 'subscript' with an argument list of type '($T5, Builtin.RawPointer)'
+//      Cannot invoke 'subscript' with an argument list of type '($T5, Builtin.RawPointer)'
+//
+//    Swift stopped to support subscripts with multiple outputs.
+//
+//    subscript (asdasd: String) -> String {
+//        get {
+//            return asdasd
+//        }
+//        set ( directoryPath ) {
+//            if let regex = NSRegularExpression(pattern: asdasd, options: expressionOptions, error: nil) {
+//                handlers.append(expression: regex, handler: { request in
+//                    let result = regex.firstMatchInString(request.url, options: self.matchingOptions, range: NSMakeRange(0, request.url.lengthOfBytesUsingEncoding(NSASCIIStringEncoding)))
+//                    let nsPath: NSString = request.url
+//                    let filesPath = directoryPath.stringByExpandingTildeInPath.stringByAppendingPathComponent(nsPath.substringWithRange(result!.rangeAtIndex(1)))
+//                    if let fileBody = String(contentsOfFile: filesPath, encoding: NSUTF8StringEncoding, error: nil) {
+//                        return HttpResponse.OK(.RAW(fileBody))
+//                    }
+//                    return HttpResponse.NotFound
+//                })
+//            }
+//        }
+//    }
     
     func routes() -> Array<String> {
         var results = [String]()
@@ -72,8 +72,10 @@ class HttpServer
                         let parser = HttpParser()
                         while let request = parser.nextHttpRequest(socket) {
                             let keepAlive = parser.supportsKeepAlive(request.headers)
-                            if let handler: Handler = self[request.url] {
-                                HttpServer.writeResponse(socket, response: handler(request), keepAlive: keepAlive)
+                            if let (expression, handler) = self.findHandler(request.url) {
+                                let capturedUrlsGroups = self.captureExpressionGroups(expression, value: request.url)
+                                let updatedRequest = HttpRequest(url: request.url, method: request.method, headers: request.headers, body: request.body, capturedUrlGroups: capturedUrlsGroups)
+                                HttpServer.writeResponse(socket, response: handler(updatedRequest), keepAlive: keepAlive)
                             } else {
                                 HttpServer.writeResponse(socket, response: HttpResponse.NotFound, keepAlive: keepAlive)
                             }
@@ -89,6 +91,23 @@ class HttpServer
         return false
     }
     
+    func findHandler(url:String) -> (NSRegularExpression, Handler)? {
+        return filter(self.handlers, { (expression: NSRegularExpression, handler) -> Bool in
+            return expression.numberOfMatchesInString(url, options: self.matchingOptions, range: NSMakeRange(0, url.lengthOfBytesUsingEncoding(NSASCIIStringEncoding))) > 0
+        }).first
+    }
+    
+    func captureExpressionGroups(expression: NSRegularExpression, value: String) -> [String] {
+        var capturedGroups = [String]()
+        if let result = expression.firstMatchInString(value, options: matchingOptions, range: NSMakeRange(0, value.lengthOfBytesUsingEncoding(NSASCIIStringEncoding))) {
+            let nsValue: NSString = value
+            for var i = 1 ; i < result.numberOfRanges ; ++i {
+                capturedGroups.append(nsValue.substringWithRange(result.rangeAtIndex(i)))
+            }
+        }
+        return capturedGroups
+    }
+    
     class func writeResponse(socket: CInt, response: HttpResponse, keepAlive: Bool) {
         Socket.writeStringUTF8(socket, string: "HTTP/1.1 \(response.statusCode()) \(response.reasonPhrase())\r\n")
         let messageBody = response.body()

+ 2 - 2
Common/Socket.swift

@@ -14,9 +14,9 @@ struct Socket {
     static func socketLastError(reason:String) -> NSError {
         let errorCode = errno
         if let errorText = String.fromCString(UnsafePointer(strerror(errorCode))) {
-            return NSError.errorWithDomain("SOCKET", code: Int(errorCode), userInfo: [NSLocalizedFailureReasonErrorKey : reason, NSLocalizedDescriptionKey : errorText])
+            return NSError(domain: "SOCKET", code: Int(errorCode), userInfo: [NSLocalizedFailureReasonErrorKey : reason, NSLocalizedDescriptionKey : errorText])
         }
-        return NSError.errorWithDomain("SOCKET", code: Int(errorCode), userInfo: nil)
+        return NSError(domain: "SOCKET", code: Int(errorCode), userInfo: nil)
     }
     
     static func tcpForListen(port: in_port_t = 8080, error:NSErrorPointer = nil) -> CInt? {

+ 27 - 1
Swifter.xcodeproj/project.pbxproj

@@ -7,6 +7,8 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		7C6A510E1A149859004924B5 /* ActiveRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C6A510D1A149859004924B5 /* ActiveRecord.swift */; };
+		7C6A510F1A149859004924B5 /* ActiveRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C6A510D1A149859004924B5 /* ActiveRecord.swift */; };
 		7C839B7419422CFF003A6950 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C839B7319422CFF003A6950 /* AppDelegate.swift */; };
 		7C839B7619422CFF003A6950 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C839B7519422CFF003A6950 /* ViewController.swift */; };
 		7C839B7919422CFF003A6950 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7C839B7719422CFF003A6950 /* Main.storyboard */; };
@@ -24,6 +26,10 @@
 		7CA4815919A2EF560030B30D /* test.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CA4815B19A2F6A60030B30D /* HttpRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CA4815A19A2F6A60030B30D /* HttpRequest.swift */; };
 		7CA4815C19A2F6A60030B30D /* HttpRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CA4815A19A2F6A60030B30D /* HttpRequest.swift */; };
+		7CB102DA1A1664B200CBA3B4 /* HttpHandlers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB102D91A1664B200CBA3B4 /* HttpHandlers.swift */; };
+		7CB102DB1A16657200CBA3B4 /* HttpHandlers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB102D91A1664B200CBA3B4 /* HttpHandlers.swift */; };
+		7CB102DD1A167FFA00CBA3B4 /* DemoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB102DC1A167FFA00CBA3B4 /* DemoServer.swift */; };
+		7CB102DE1A1680EA00CBA3B4 /* DemoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB102DC1A167FFA00CBA3B4 /* DemoServer.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -40,6 +46,7 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		7C6A510D1A149859004924B5 /* ActiveRecord.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveRecord.swift; sourceTree = "<group>"; };
 		7C839B6E19422CFF003A6950 /* Swifter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Swifter.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		7C839B7219422CFF003A6950 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		7C839B7319422CFF003A6950 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -54,6 +61,8 @@
 		7CA4814D19A2EED00030B30D /* Socket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Socket.swift; sourceTree = "<group>"; };
 		7CA4815719A2EF2B0030B30D /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = "<group>"; };
 		7CA4815A19A2F6A60030B30D /* HttpRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpRequest.swift; sourceTree = "<group>"; };
+		7CB102D91A1664B200CBA3B4 /* HttpHandlers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpHandlers.swift; sourceTree = "<group>"; };
+		7CB102DC1A167FFA00CBA3B4 /* DemoServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DemoServer.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -74,6 +83,14 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		7C6A510C1A149843004924B5 /* ActiveRecord */ = {
+			isa = PBXGroup;
+			children = (
+				7C6A510D1A149859004924B5 /* ActiveRecord.swift */,
+			);
+			path = ActiveRecord;
+			sourceTree = "<group>";
+		};
 		7C839B6519422CFF003A6950 = {
 			isa = PBXGroup;
 			children = (
@@ -125,11 +142,14 @@
 		7CA4814919A2EED00030B30D /* Common */ = {
 			isa = PBXGroup;
 			children = (
+				7C6A510C1A149843004924B5 /* ActiveRecord */,
 				7CA4815A19A2F6A60030B30D /* HttpRequest.swift */,
 				7CA4814A19A2EED00030B30D /* HttpParser.swift */,
 				7CA4814B19A2EED00030B30D /* HttpResponse.swift */,
+				7CB102D91A1664B200CBA3B4 /* HttpHandlers.swift */,
 				7CA4814C19A2EED00030B30D /* HttpServer.swift */,
 				7CA4814D19A2EED00030B30D /* Socket.swift */,
+				7CB102DC1A167FFA00CBA3B4 /* DemoServer.swift */,
 			);
 			path = Common;
 			sourceTree = "<group>";
@@ -233,7 +253,10 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				7C6A510E1A149859004924B5 /* ActiveRecord.swift in Sources */,
 				7CA4815019A2EED00030B30D /* HttpResponse.swift in Sources */,
+				7CB102DA1A1664B200CBA3B4 /* HttpHandlers.swift in Sources */,
+				7CB102DD1A167FFA00CBA3B4 /* DemoServer.swift in Sources */,
 				7C839B7619422CFF003A6950 /* ViewController.swift in Sources */,
 				7CA4815419A2EED00030B30D /* Socket.swift in Sources */,
 				7CA4815219A2EED00030B30D /* HttpServer.swift in Sources */,
@@ -248,10 +271,13 @@
 			buildActionMask = 2147483647;
 			files = (
 				7CA4815119A2EED00030B30D /* HttpResponse.swift in Sources */,
+				7CB102DE1A1680EA00CBA3B4 /* DemoServer.swift in Sources */,
 				7CA4814F19A2EED00030B30D /* HttpParser.swift in Sources */,
 				7CA4815519A2EED00030B30D /* Socket.swift in Sources */,
+				7C6A510F1A149859004924B5 /* ActiveRecord.swift in Sources */,
 				7CA4815319A2EED00030B30D /* HttpServer.swift in Sources */,
 				7CA4813E19A2EA8D0030B30D /* main.swift in Sources */,
+				7CB102DB1A16657200CBA3B4 /* HttpHandlers.swift in Sources */,
 				7CA4815C19A2F6A60030B30D /* HttpRequest.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -306,7 +332,7 @@
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				METAL_ENABLE_DEBUG_INFO = YES;
-				ONLY_ACTIVE_ARCH = NO;
+				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				TARGETED_DEVICE_FAMILY = "1,2";

+ 9 - 9
Swifter.xcodeproj/project.xcworkspace/xcshareddata/Swifter.xccheckout

@@ -10,31 +10,31 @@
 	<string>Swifter</string>
 	<key>IDESourceControlProjectOriginsDictionary</key>
 	<dict>
-		<key>9BA50FC1-8933-46EC-8469-51B02ED36C86</key>
-		<string>ssh://github.com/glock45/swifter.git</string>
+		<key>75224C288D14A799245F99223249EF48FF5DC280</key>
+		<string>github.com:glock45/swifter.git</string>
 	</dict>
 	<key>IDESourceControlProjectPath</key>
-	<string>Swifter.xcodeproj/project.xcworkspace</string>
+	<string>Swifter.xcodeproj</string>
 	<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
 	<dict>
-		<key>9BA50FC1-8933-46EC-8469-51B02ED36C86</key>
+		<key>75224C288D14A799245F99223249EF48FF5DC280</key>
 		<string>../..</string>
 	</dict>
 	<key>IDESourceControlProjectURL</key>
-	<string>ssh://github.com/glock45/swifter.git</string>
+	<string>github.com:glock45/swifter.git</string>
 	<key>IDESourceControlProjectVersion</key>
-	<integer>110</integer>
+	<integer>111</integer>
 	<key>IDESourceControlProjectWCCIdentifier</key>
-	<string>9BA50FC1-8933-46EC-8469-51B02ED36C86</string>
+	<string>75224C288D14A799245F99223249EF48FF5DC280</string>
 	<key>IDESourceControlProjectWCConfigurations</key>
 	<array>
 		<dict>
 			<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
 			<string>public.vcs.git</string>
 			<key>IDESourceControlWCCIdentifierKey</key>
-			<string>9BA50FC1-8933-46EC-8469-51B02ED36C86</string>
+			<string>75224C288D14A799245F99223249EF48FF5DC280</string>
 			<key>IDESourceControlWCCName</key>
-			<string>Swifter</string>
+			<string>swifter</string>
 		</dict>
 	</array>
 </dict>

BIN
Swifter.xcodeproj/project.xcworkspace/xcuserdata/damiankolakowski.xcuserdatad/UserInterfaceState.xcuserstate


+ 10 - 0
Swifter.xcodeproj/project.xcworkspace/xcuserdata/damiankolakowski.xcuserdatad/WorkspaceSettings.xcsettings

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
+	<true/>
+	<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
+	<false/>
+</dict>
+</plist>

+ 214 - 40
Swifter.xcodeproj/xcuserdata/damiankolakowski.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -199,42 +199,42 @@
             shouldBeEnabled = "No"
             ignoreCount = "0"
             continueAfterRunningActions = "No"
-            filePath = "Common/HttpServer.swift"
-            timestampString = "430108876.844745"
+            filePath = "Common/HttpResponse.swift"
+            timestampString = "430110038.828632"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "44"
-            endingLineNumber = "44"
-            landmarkName = "HttpServer"
-            landmarkType = "3">
+            startingLineNumber = "35"
+            endingLineNumber = "35"
+            landmarkName = "data()"
+            landmarkType = "5">
             <Locations>
                <Location
                   shouldBeEnabled = "No"
                   ignoreCount = "0"
                   continueAfterRunningActions = "No"
-                  symbolName = "SwifterOSX.HttpServer.subscript.setter (Swift.String) -&gt; Swift.String"
+                  symbolName = "SwifterOSX.HttpResponseBody.data (SwifterOSX.HttpResponseBody)() -&gt; Swift.Optional&lt;Swift.String&gt;"
                   moduleName = "SwifterOSX"
-                  urlString = "file:///Users/damiankolakowski/Desktop/Swifter/Common/HttpServer.swift"
-                  timestampString = "430108980.866628"
+                  urlString = "file:///Users/damiankolakowski/Desktop/Swifter/Common/HttpResponse.swift"
+                  timestampString = "430110038.833456"
                   startingColumnNumber = "9223372036854775807"
                   endingColumnNumber = "9223372036854775807"
-                  startingLineNumber = "44"
-                  endingLineNumber = "44"
-                  offsetFromSymbolStart = "43">
+                  startingLineNumber = "35"
+                  endingLineNumber = "35"
+                  offsetFromSymbolStart = "3084">
                </Location>
                <Location
                   shouldBeEnabled = "No"
                   ignoreCount = "0"
                   continueAfterRunningActions = "No"
-                  symbolName = "SwifterOSX.HttpServer.subscript.setter (Swift.String) -&gt; Swift.String"
+                  symbolName = "SwifterOSX.HttpResponseBody.data (SwifterOSX.HttpResponseBody)() -&gt; Swift.Optional&lt;Swift.String&gt;"
                   moduleName = "SwifterOSX"
-                  urlString = "file:///Users/damiankolakowski/Desktop/Swifter/Common/HttpServer.swift"
-                  timestampString = "430108980.866808"
+                  urlString = "file:///Users/damiankolakowski/Desktop/Swifter/Common/HttpResponse.swift"
+                  timestampString = "430110038.833645"
                   startingColumnNumber = "9223372036854775807"
                   endingColumnNumber = "9223372036854775807"
-                  startingLineNumber = "44"
-                  endingLineNumber = "44"
-                  offsetFromSymbolStart = "850">
+                  startingLineNumber = "35"
+                  endingLineNumber = "35"
+                  offsetFromSymbolStart = "3643">
                </Location>
             </Locations>
          </BreakpointContent>
@@ -246,13 +246,13 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "430111339.558837"
+            timestampString = "437665731.313686"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "46"
-            endingLineNumber = "46"
-            landmarkName = "HttpServer"
-            landmarkType = "3">
+            startingLineNumber = "67"
+            endingLineNumber = "67"
+            landmarkName = "start(listenPort:error:)"
+            landmarkType = "5">
          </BreakpointContent>
       </BreakpointProxy>
       <BreakpointProxy
@@ -261,45 +261,219 @@
             shouldBeEnabled = "No"
             ignoreCount = "0"
             continueAfterRunningActions = "No"
-            filePath = "Common/HttpResponse.swift"
-            timestampString = "430110038.828632"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437665731.313686"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "35"
-            endingLineNumber = "35"
-            landmarkName = "data()"
+            startingLineNumber = "69"
+            endingLineNumber = "69"
+            landmarkName = "start(listenPort:error:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437665731.313686"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "71"
+            endingLineNumber = "71"
+            landmarkName = "start(listenPort:error:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437665731.313686"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "73"
+            endingLineNumber = "73"
+            landmarkName = "start(listenPort:error:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437665731.313686"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "75"
+            endingLineNumber = "75"
+            landmarkName = "start(listenPort:error:)"
             landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437675481.833013"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "79"
+            endingLineNumber = "79"
+            landmarkName = "start(listenPort:error:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437675481.833013"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "80"
+            endingLineNumber = "80"
+            landmarkName = "start(listenPort:error:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/ActiveRecord/ActiveRecord.swift"
+            timestampString = "437582232.832834"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "15"
+            endingLineNumber = "15"
+            landmarkName = "SwifterActiveRecord"
+            landmarkType = "3">
             <Locations>
                <Location
                   shouldBeEnabled = "No"
                   ignoreCount = "0"
                   continueAfterRunningActions = "No"
-                  symbolName = "SwifterOSX.HttpResponseBody.data (SwifterOSX.HttpResponseBody)() -&gt; Swift.Optional&lt;Swift.String&gt;"
+                  symbolName = "SwifterOSX.SwifterActiveRecord.deinit"
                   moduleName = "SwifterOSX"
-                  urlString = "file:///Users/damiankolakowski/Desktop/Swifter/Common/HttpResponse.swift"
-                  timestampString = "430110038.833456"
+                  urlString = "file:///Users/damiankolakowski/Desktop/swifter/Common/ActiveRecord/ActiveRecord.swift"
+                  timestampString = "437665731.59783"
                   startingColumnNumber = "9223372036854775807"
                   endingColumnNumber = "9223372036854775807"
-                  startingLineNumber = "35"
-                  endingLineNumber = "35"
-                  offsetFromSymbolStart = "3084">
+                  startingLineNumber = "15"
+                  endingLineNumber = "15"
+                  offsetFromSymbolStart = "8">
                </Location>
                <Location
                   shouldBeEnabled = "No"
                   ignoreCount = "0"
                   continueAfterRunningActions = "No"
-                  symbolName = "SwifterOSX.HttpResponseBody.data (SwifterOSX.HttpResponseBody)() -&gt; Swift.Optional&lt;Swift.String&gt;"
+                  symbolName = "SwifterOSX.SwifterActiveRecord.__deallocating_deinit"
                   moduleName = "SwifterOSX"
-                  urlString = "file:///Users/damiankolakowski/Desktop/Swifter/Common/HttpResponse.swift"
-                  timestampString = "430110038.833645"
+                  urlString = "file:///Users/damiankolakowski/Desktop/swifter/Common/ActiveRecord/ActiveRecord.swift"
+                  timestampString = "437665731.598002"
                   startingColumnNumber = "9223372036854775807"
                   endingColumnNumber = "9223372036854775807"
-                  startingLineNumber = "35"
-                  endingLineNumber = "35"
-                  offsetFromSymbolStart = "3643">
+                  startingLineNumber = "15"
+                  endingLineNumber = "15"
+                  offsetFromSymbolStart = "12">
                </Location>
             </Locations>
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/ActiveRecord/ActiveRecord.swift"
+            timestampString = "437665027.659897"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "46"
+            endingLineNumber = "46">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpHandlers.swift"
+            timestampString = "437675574.547105"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "15"
+            endingLineNumber = "15"
+            landmarkName = "directory(_:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437675622.074193"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "101"
+            endingLineNumber = "101"
+            landmarkName = "captureExpressionGroups(_:value:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/DemoServer.swift"
+            timestampString = "437682950.226404"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "46"
+            endingLineNumber = "46"
+            landmarkName = "demoServer(_:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "437682692.747736"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "76"
+            endingLineNumber = "76"
+            landmarkName = "start(listenPort:error:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 4 - 57
Swifter/AppDelegate.swift

@@ -13,66 +13,13 @@ import UIKit
 class AppDelegate: UIResponder, UIApplicationDelegate {
     
     var window: UIWindow?
-    let server: HttpServer = HttpServer()
+    var server: HttpServer?
     
     func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
-        if let resDir = NSBundle.mainBundle().resourcePath {
-            server["/resources/(.+)"] = resDir
-        }
-        server["/test"] = { request in
-            var headersInfo = ""
-            for (name, value) in request.headers {
-                headersInfo += "\(name) : \(value)<br>"
-            }
-            let response = "<html><body>Url: \(request.url)<br>Method: \(request.method)<br>\(headersInfo)</body></html>"
-            return .OK(.RAW(response))
-        }
-        server["/json"] = { request in
-            return .OK(.JSON(["posts" : [[ "id" : 1, "message" : "hello world"],[ "id" : 2, "message" : "sample message"]], "new_updates" : false]))
-        }
-        server["/redirect"] = { request in
-            return .MovedPermanently("http://www.google.com")
-        }
-        server["/long"] = { request in
-            var longResponse = ""
-            for k in 0..<1000 { longResponse += "(\(k)),->" }
-            return .OK(.RAW(longResponse))
-        }
-        server["/demo"] = { request in
-            return .OK(.RAW("<html><body><center><h2>Hello Swift</h2>" +
-                "<img src=\"https://devimages.apple.com.edgekey.net/swift/images/swift-hero_2x.png\"/><br>" +
-                "<h4>\(UIDevice().name), \(UIDevice().systemVersion)</h4></center></body></html>"))
-        }
-        server["/login"] = { request in
-            println(">> request method:\(request.method.uppercaseString)")
-            var method = request.method.uppercaseString
-            if method == "GET" {
-                //TODO: should copy the file to document path of app's
-                //TODO: should not use the absolute path
-                if let html = String.stringWithContentsOfFile("/Users/wshan/Workspace/swifter/www/views/login.html", encoding: NSUTF8StringEncoding, error: nil){
-                    return .OK(.RAW(html))
-                }else{
-                    return .NotFound
-                }
-            }else if method == "POST"{
-                println(">> post data: \(NSString(data:request.responseData!,encoding:NSUTF8StringEncoding))")
-                return .MovedPermanently("http://github.com")
-            }
-            
-            return .NotFound
-        }
-        server["/"] = { request in
-            var listPage = "<html><body>Available services:<br><ul>"
-            for item in self.server.routes() {
-                listPage += "<li><a href=\"\(item)\">\(item)</a></li>"
-            }
-            listPage += "</ul></body></html>"
-            return .OK(.RAW(listPage))
-        }
-
-        
+        let server = demoServer(NSBundle.mainBundle().resourcePath)
+        self.server = server
         var error: NSError?
-        if !server.start(error: &error) {
+        if server.start(error: &error) {
             println("Server start error: \(error)")
         }
         return true

+ 1 - 36
SwifterOSX/main.swift

@@ -8,42 +8,7 @@
 
 import Foundation
 
-let server: HttpServer = HttpServer()
-
-server["/resources/(.+)"] = "~/"
-
-server["/test"] = { request in
-    var headersInfo = ""
-    for (name, value) in request.headers {
-        headersInfo += "\(name) : \(value)<br>"
-    }
-    let response = "<html><body>Url: \(request.url)<br>Method: \(request.method)<br>\(headersInfo)</body></html>"
-    return .OK(.RAW(response))
-}
-server["/json"] = { request in
-    return .OK(.JSON(["posts" : [[ "id" : 1, "message" : "hello world"],[ "id" : 2, "message" : "sample message"]], "new_updates" : false]))
-}
-server["/redirect"] = { request in
-    return .MovedPermanently("http://www.google.com")
-}
-server["/long"] = { request in
-    var longResponse = ""
-    for k in 0..<1000 { longResponse += "(\(k)),->" }
-    return .OK(.RAW(longResponse))
-}
-server["/demo"] = { request in
-    return .OK(.RAW("<html><body><center><h2>Hello Swift</h2>" +
-        "<img src=\"https://devimages.apple.com.edgekey.net/swift/images/swift-hero_2x.png\"/><br>" +
-        "<h4>\(NSHost.currentHost().localizedName)</h4></center></body></html>"))
-}
-server["/"] = { request in
-    var listPage = "<html><body>Available services:<br><ul>"
-    for item in server.routes() {
-        listPage += "<li><a href=\"\(item)\">\(item)</a></li>"
-    }
-    listPage += "</ul></body></html>"
-    return .OK(.RAW(listPage))
-}
+let server = demoServer("~/")
 
 var error: NSError?