Просмотр исходного кода

Fixed router class for url with query section.
Cleanup.

Damian Kołakowski 10 лет назад
Родитель
Сommit
417964c4f1

+ 6 - 3
Sources/Swifter/DemoServer.swift

@@ -18,7 +18,11 @@ public func demoServer(publicDir: String?) -> HttpServer {
     server["/"] = { r in
         var listPage = "Available services:<br><ul>"
         for (method, path) in server.routes {
-            listPage += "<li><a href=\"\(path)\">\(method): \(path)</a></li>"
+            if let m = method {
+                listPage += "<li><a href=\"\(path)\">\(m): \(path)</a></li>"
+            } else {
+                listPage += "<li><a href=\"\(path)\">\(path)</a></li>"
+            }
         }
         listPage += "</ul>"
         return .OK(.Html(listPage))
@@ -39,7 +43,7 @@ public func demoServer(publicDir: String?) -> HttpServer {
         for token in r.params {
             pathParamsInfo += "\(token.0) : \(token.1)<br>"
         }
-        return .OK(.Html("<h3>Address: \(r.address)</h3><h3>Url:</h3> \(r.url)<h3>Method: \(r.method)</h3><h3>Headers:</h3>\(headersInfo)<h3>Query:</h3>\(queryParamsInfo)<h3>Path params:</h3>\(pathParamsInfo)"))
+        return .OK(.Html("<h3>Address: \(r.address)</h3><h3>Url:</h3> \(r.url)<h3>Method:</h3>\(r.method)<h3>Headers:</h3>\(headersInfo)<h3>Query:</h3>\(queryParamsInfo)<h3>Path params:</h3>\(pathParamsInfo)"))
     }
     
     server.GET["/upload"] = { r in
@@ -48,7 +52,6 @@ public func demoServer(publicDir: String?) -> HttpServer {
             html.getBytes(&array, length: html.length)
             return HttpResponse.RAW(200, "OK", nil, array)
         }
-        
         return .NotFound
     }
     

+ 6 - 4
Sources/Swifter/HttpParser.swift

@@ -12,7 +12,6 @@
 
 
 enum HttpParserError: ErrorType {
-    case ReadBodyFailed(String)
     case InvalidStatusLine(String)
 }
 
@@ -28,7 +27,7 @@ class HttpParser {
         var request = HttpRequest()
         request.method = statusLineTokens[0]
         request.url = statusLineTokens[1]
-        request.queryParams = extractUrlParams(request.url)
+        request.queryParams = extractQueryParams(request.url)
         request.headers = try readHeaders(socket)
         if let contentLength = request.headers["content-length"], let contentLengthValue = Int(contentLength) {
             request.body = try readBody(socket, size: contentLengthValue)
@@ -36,15 +35,18 @@ class HttpParser {
         return request
     }
     
-    private func extractUrlParams(url: String) -> [(String, String)] {
+    private func extractQueryParams(url: String) -> [(String, String)] {
         guard let query = url.split("?").last else {
             return []
         }
         return query.split("&").map { (param: String) -> (String, String) in
             let tokens = param.split("=")
-            guard let name = tokens.first, value = tokens.last else {
+            guard let name = tokens.first else {
                 return ("", "")
             }
+            guard let value = tokens.last where tokens.count > 1 else {
+                return (name.removePercentEncoding(), "")
+            }
             return (name.removePercentEncoding(), value.removePercentEncoding())
         }
     }

+ 11 - 4
Sources/Swifter/HttpRouter.swift

@@ -15,19 +15,19 @@ public class HttpRouter {
     }
     
     public func register(method: String?, path: String, handler: HttpRequest -> HttpResponse) {
-        handlers.append((method, path.split("/"), handler))
+        handlers.append((method, stripQuery(path).split("/"), handler))
         handlers.sortInPlace { $0.0.pattern.count < $0.1.pattern.count }
     }
     
     public func unregister(method: String?, path: String) {
-        let tokens = path.split("/")
+        let pathTokens = stripQuery(path).split("/")
         handlers = handlers.filter { (meth, pattern, _) -> Bool in
-            return meth != method || pattern != tokens
+            return meth != method || pattern != pathTokens
         }
     }
     
     public func select(method: String?, url: String) -> ([String: String], HttpRequest -> HttpResponse)? {
-        let urlTokens = url.split("/")
+        let urlTokens = stripQuery(url).split("/")
         for (meth, pattern, handler) in handlers {
             if meth == nil || meth! == method {
                 if let params = matchParams(pattern, valueTokens: urlTokens) {
@@ -65,4 +65,11 @@ public class HttpRouter {
         }
         return params
     }
+    
+    private func stripQuery(path: String) -> String {
+        if let path = path.split("?").first {
+            return path
+        }
+        return path
+    }
 }

+ 13 - 14
Sources/Swifter/HttpServer.swift

@@ -13,45 +13,44 @@ public class HttpServer: HttpServerIO {
     private let router = HttpRouter()
     
     public var routes: [(method: String?, path: String)] {
-        return router.routes()
+        return router.routes();
     }
     
     public subscript(path: String) -> (HttpRequest -> HttpResponse)? {
         set {
             if let handler = newValue {
                 self.router.register(nil, path: path, handler: handler)
-            }
-            else {
+            } else {
                 self.router.unregister(nil, path: path)
             }
         }
         get { return nil }
     }
     
-    public lazy var DELETE : Route = self.lazyBuild("DELETE")
-    public lazy var UPDATE : Route = self.lazyBuild("UPDATE")
-    public lazy var HEAD   : Route = self.lazyBuild("HEAD")
-    public lazy var POST   : Route = self.lazyBuild("POST")
-    public lazy var GET    : Route = self.lazyBuild("GET")
-    public lazy var PUT    : Route = self.lazyBuild("PUT")
+    public lazy var DELETE : Route = self.newRoute("DELETE")
+    public lazy var UPDATE : Route = self.newRoute("UPDATE")
+    public lazy var HEAD   : Route = self.newRoute("HEAD")
+    public lazy var POST   : Route = self.newRoute("POST")
+    public lazy var GET    : Route = self.newRoute("GET")
+    public lazy var PUT    : Route = self.newRoute("PUT")
     
     public struct Route {
         public let method: String
-        public let server: HttpServer
+        public let router: HttpRouter
         public subscript(path: String) -> (HttpRequest -> HttpResponse)? {
             set {
                 if let handler = newValue {
-                    server.router.register(method, path: path, handler: handler)
+                    router.register(method, path: path, handler: handler)
                 } else {
-                    server.router.unregister(method, path: path)
+                    router.unregister(method, path: path)
                 }
             }
             get { return nil }
         }
     }
     
-    private func lazyBuild(method: String) -> Route {
-        return Route(method: method, server: self)
+    private func newRoute(method: String) -> Route {
+        return Route(method: method, router: self.router)
     }
     
     override public func select(method: String, url: String) -> ([String : String], HttpRequest -> HttpResponse) {

+ 2 - 7
Sources/Swifter/Socket.swift

@@ -27,7 +27,7 @@ enum SocketError: ErrorType {
 
 public class Socket: Hashable, Equatable {
     
-    public class func tcpSocketForListen(port: in_port_t = 8080, maxPendingConnection: Int32 = SOMAXCONN) throws -> Socket {
+    public class func tcpSocketForListen(port: in_port_t, maxPendingConnection: Int32 = SOMAXCONN) throws -> Socket {
         
         #if os(Linux)
             let socketFileDescriptor = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0)
@@ -96,12 +96,7 @@ public class Socket: Hashable, Equatable {
     }
     
     public func acceptClientSocket() throws -> Socket {
-        #if os(Linux)
-            var addr = sockaddr()
-        #else
-            var addr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
-        #endif
-        
+        var addr = sockaddr()        
         var len: socklen_t = 0
         let clientSocket = accept(self.socketFileDescriptor, &addr, &len)
         if clientSocket == -1 {

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


+ 80 - 16
Swifter.xcodeproj/xcuserdata/damiankolakowski.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -885,11 +885,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Sources/Swifter/HttpParser.swift"
-            timestampString = "472077470.733846"
+            timestampString = "472213513.123086"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "21"
-            endingLineNumber = "21"
+            startingLineNumber = "20"
+            endingLineNumber = "20"
             landmarkName = "readHttpRequest(_:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -1157,11 +1157,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Sources/Swifter/DemoServer.swift"
-            timestampString = "472077470.733846"
+            timestampString = "472213774.507536"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "53"
-            endingLineNumber = "53"
+            startingLineNumber = "56"
+            endingLineNumber = "56"
             landmarkName = "demoServer(_:)"
             landmarkType = "7">
             <Locations>
@@ -1281,15 +1281,15 @@
       <BreakpointProxy
          BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
          <BreakpointContent
-            shouldBeEnabled = "Yes"
+            shouldBeEnabled = "No"
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Sources/Swifter/HttpServerIO.swift"
-            timestampString = "472077581.497308"
+            timestampString = "472078003.280977"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "31"
-            endingLineNumber = "31"
+            startingLineNumber = "29"
+            endingLineNumber = "29"
             landmarkName = "start(_:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -1301,11 +1301,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Sources/Swifter/HttpServer.swift"
-            timestampString = "472077589.417334"
+            timestampString = "472213513.123086"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "41"
-            endingLineNumber = "41"
+            startingLineNumber = "42"
+            endingLineNumber = "42"
             landmarkName = "Route"
             landmarkType = "3">
          </BreakpointContent>
@@ -1317,14 +1317,78 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Sources/Swifter/HttpServer.swift"
-            timestampString = "472077591.266882"
+            timestampString = "472213513.123086"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "44"
-            endingLineNumber = "44"
+            startingLineNumber = "45"
+            endingLineNumber = "45"
             landmarkName = "Route"
             landmarkType = "3">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Sources/Swifter/HttpServerIO.swift"
+            timestampString = "472078052.504852"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "56"
+            endingLineNumber = "56"
+            landmarkName = "select(_:url:)"
+            landmarkType = "5">
+            <Locations>
+               <Location
+                  shouldBeEnabled = "No"
+                  ignoreCount = "0"
+                  continueAfterRunningActions = "No"
+                  symbolName = "SwifterSampleOSX.HttpServerIO.select (SwifterSampleOSX.HttpServerIO)(Swift.String, url : Swift.String) -&gt; (Swift.Dictionary&lt;Swift.String, Swift.String&gt;, (SwifterSampleOSX.HttpRequest) -&gt; SwifterSampleOSX.HttpResponse)"
+                  moduleName = "SwifterSampleOSX"
+                  usesParentBreakpointCondition = "Yes"
+                  urlString = "file:///Users/damiankolakowski/Desktop/swifter/Sources/Swifter/HttpServerIO.swift"
+                  timestampString = "472213635.095724"
+                  startingColumnNumber = "9223372036854775807"
+                  endingColumnNumber = "9223372036854775807"
+                  startingLineNumber = "56"
+                  endingLineNumber = "56"
+                  offsetFromSymbolStart = "40">
+               </Location>
+               <Location
+                  shouldBeEnabled = "No"
+                  ignoreCount = "0"
+                  continueAfterRunningActions = "No"
+                  symbolName = "SwifterSampleOSX.HttpServerIO.(select (SwifterSampleOSX.HttpServerIO) -&gt; (Swift.String, url : Swift.String) -&gt; (Swift.Dictionary&lt;Swift.String, Swift.String&gt;, (SwifterSampleOSX.HttpRequest) -&gt; SwifterSampleOSX.HttpResponse)).(closure #1)"
+                  moduleName = "SwifterSampleOSX"
+                  usesParentBreakpointCondition = "Yes"
+                  urlString = "file:///Users/damiankolakowski/Desktop/swifter/Sources/Swifter/HttpServerIO.swift"
+                  timestampString = "472213635.096005"
+                  startingColumnNumber = "9223372036854775807"
+                  endingColumnNumber = "9223372036854775807"
+                  startingLineNumber = "56"
+                  endingLineNumber = "56"
+                  offsetFromSymbolStart = "169">
+               </Location>
+            </Locations>
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Sources/Swifter/HttpServer.swift"
+            timestampString = "472213513.123086"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "57"
+            endingLineNumber = "57"
+            landmarkName = "select(_:url:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>