Преглед изворни кода

Added HttpHandlers class as a factory for common handlers.

Damian Kołakowski пре 11 година
родитељ
комит
73c6382e15

+ 6 - 0
Common/ActiveRecord/ActiveRecord.swift

@@ -31,6 +31,12 @@ class SwifterActiveRecord /* Probbaly we will use generics and not follow Ruby's
         return results
     }
     
+    //func findBy(
+    
+    func all() -> Array<String> {
+        return []
+    }
+    
     func commit(error: NSErrorPointer) -> Bool {
         //TODO commit changes to DB.
         return false

+ 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
+        }
+    }
+}

+ 1 - 1
Common/HttpParser.swift

@@ -33,7 +33,7 @@ class HttpParser {
                 }
                 println(requestBody)
                 let body = requestBody.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
-                return HttpRequest(url: path, method: method, headers: headers, body: body)
+                return HttpRequest(url: path, method: method, headers: headers, body: body, capturedUrlGroups: [])
             }
         }
         return nil

+ 1 - 0
Common/HttpRequest.swift

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

+ 22 - 10
Common/HttpServer.swift

@@ -19,12 +19,6 @@ 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 ) {
@@ -52,8 +46,7 @@ class HttpServer
 //                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)))
+//                    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))
 //                    }
@@ -79,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.captureGroups(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)
                             }
@@ -96,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 captureGroups(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()

+ 6 - 0
Swifter.xcodeproj/project.pbxproj

@@ -26,6 +26,8 @@
 		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 */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -57,6 +59,7 @@
 		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>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -140,6 +143,7 @@
 				7CA4815A19A2F6A60030B30D /* HttpRequest.swift */,
 				7CA4814A19A2EED00030B30D /* HttpParser.swift */,
 				7CA4814B19A2EED00030B30D /* HttpResponse.swift */,
+				7CB102D91A1664B200CBA3B4 /* HttpHandlers.swift */,
 				7CA4814C19A2EED00030B30D /* HttpServer.swift */,
 				7CA4814D19A2EED00030B30D /* Socket.swift */,
 			);
@@ -247,6 +251,7 @@
 			files = (
 				7C6A510E1A149859004924B5 /* ActiveRecord.swift in Sources */,
 				7CA4815019A2EED00030B30D /* HttpResponse.swift in Sources */,
+				7CB102DA1A1664B200CBA3B4 /* HttpHandlers.swift in Sources */,
 				7C839B7619422CFF003A6950 /* ViewController.swift in Sources */,
 				7CA4815419A2EED00030B30D /* Socket.swift in Sources */,
 				7CA4815219A2EED00030B30D /* HttpServer.swift in Sources */,
@@ -266,6 +271,7 @@
 				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;

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


+ 113 - 21
Swifter.xcodeproj/xcuserdata/damiankolakowski.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -246,11 +246,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "437337013.97942"
+            timestampString = "437665731.313686"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "68"
-            endingLineNumber = "68"
+            startingLineNumber = "67"
+            endingLineNumber = "67"
             landmarkName = "start(listenPort:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -262,11 +262,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "437337022.402616"
+            timestampString = "437665731.313686"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "70"
-            endingLineNumber = "70"
+            startingLineNumber = "69"
+            endingLineNumber = "69"
             landmarkName = "start(listenPort:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -278,11 +278,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "437337567.88339"
+            timestampString = "437665731.313686"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "72"
-            endingLineNumber = "72"
+            startingLineNumber = "71"
+            endingLineNumber = "71"
             landmarkName = "start(listenPort:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -294,11 +294,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "437337586.685501"
+            timestampString = "437665731.313686"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "74"
-            endingLineNumber = "74"
+            startingLineNumber = "73"
+            endingLineNumber = "73"
             landmarkName = "start(listenPort:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -310,11 +310,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "437337595.019408"
+            timestampString = "437665731.313686"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "76"
-            endingLineNumber = "76"
+            startingLineNumber = "75"
+            endingLineNumber = "75"
             landmarkName = "start(listenPort:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -326,11 +326,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "437337595.807238"
+            timestampString = "437675481.833013"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "78"
-            endingLineNumber = "78"
+            startingLineNumber = "79"
+            endingLineNumber = "79"
             landmarkName = "start(listenPort:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -342,14 +342,106 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "437337638.220209"
+            timestampString = "437675481.833013"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "79"
-            endingLineNumber = "79"
+            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.SwifterActiveRecord.deinit"
+                  moduleName = "SwifterOSX"
+                  urlString = "file:///Users/damiankolakowski/Desktop/swifter/Common/ActiveRecord/ActiveRecord.swift"
+                  timestampString = "437665731.59783"
+                  startingColumnNumber = "9223372036854775807"
+                  endingColumnNumber = "9223372036854775807"
+                  startingLineNumber = "15"
+                  endingLineNumber = "15"
+                  offsetFromSymbolStart = "8">
+               </Location>
+               <Location
+                  shouldBeEnabled = "No"
+                  ignoreCount = "0"
+                  continueAfterRunningActions = "No"
+                  symbolName = "SwifterOSX.SwifterActiveRecord.__deallocating_deinit"
+                  moduleName = "SwifterOSX"
+                  urlString = "file:///Users/damiankolakowski/Desktop/swifter/Common/ActiveRecord/ActiveRecord.swift"
+                  timestampString = "437665731.598002"
+                  startingColumnNumber = "9223372036854775807"
+                  endingColumnNumber = "9223372036854775807"
+                  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 = "captureGroups(_:value:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 3 - 3
Swifter/AppDelegate.swift

@@ -16,9 +16,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     let server: HttpServer = HttpServer()
     
     func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
-//        if let resDir = NSBundle.mainBundle().resourcePath {
-//            server["/resources/(.+)"] = resDir
-//        }
+        if let resDir = NSBundle.mainBundle().resourcePath {
+            server["/resources/(.+)"] = HttpHandlers.directory(resDir)
+        }
         server["/test"] = { request in
             var headersInfo = ""
             for (name, value) in request.headers {

+ 2 - 2
SwifterOSX/main.swift

@@ -8,9 +8,9 @@
 
 import Foundation
 
-let server: HttpServer = HttpServer()
+let server = HttpServer()
 
-//server["/resources/(.+)"] = "~/"
+server["/resources/(.+)"] = HttpHandlers.directory("~/")
 
 server["/test"] = { request in
     var headersInfo = ""