Browse Source

Fix for https://github.com/httpswift/swifter/issues/166.

Damian Kołakowski 10 years ago
parent
commit
821c369ab1

+ 1 - 2
Sources/Swifter/DemoServer.swift

@@ -17,8 +17,7 @@ public func demoServer(_ publicDir: String) -> HttpServer {
     
     let server = HttpServer()
     
-    server["/public/:path"] = shareFilesFromDirectory(publicDir)
-    server["/public/"] = shareFilesFromDirectory(publicDir)    // needed to serve index file at root level
+    server["/shared/:path"] = shareFilesFromDirectory(publicDir)
     
     server["/files/:path"] = directoryBrowser("/")
     

+ 2 - 0
Sources/Swifter/File.swift

@@ -23,6 +23,8 @@ public enum FileError: ErrorProtocol {
 
 public class File {
     
+    public static var PATH_SEPARATOR = "/"
+    
     public static func openNewForWriting(_ path: String) throws -> File {
         return try openFileForMode(path, "wb")
     }

+ 18 - 9
Sources/Swifter/Files.swift

@@ -7,19 +7,28 @@
 
 import Foundation
 
-public func shareFilesFromDirectory(_ directoryPath: String) -> ((HttpRequest) -> HttpResponse) {
+public func shareFilesFromDirectory(_ directoryPath: String, defaults: [String] = ["index.html", "default.html"]) -> ((HttpRequest) -> HttpResponse) {
     return { r in
         guard let fileRelativePath = r.params.first else {
             return .notFound
         }
-        let absolutePath = directoryPath + "/" + fileRelativePath.1
-        guard let file = try? File.openForReading(absolutePath) else {
-            return .notFound
+        if fileRelativePath.value.isEmpty {
+            for path in defaults {
+                if let file = try? File.openForReading(directoryPath + File.PATH_SEPARATOR + path) {
+                    return .raw(200, "OK", [:], { writer in
+                        writer.write(file)
+                        file.close()
+                    })
+                }
+            }
+        }
+        if let file = try? File.openForReading(directoryPath + File.PATH_SEPARATOR + fileRelativePath.value) {
+            return .raw(200, "OK", [:], { writer in
+                writer.write(file)
+                file.close()
+            })
         }
-        return .raw(200, "OK", [:], { writer in
-            writer.write(file)
-            file.close()
-        })
+        return .notFound
     }
 }
 
@@ -28,7 +37,7 @@ public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) {
         guard let (_, value) = r.params.first else {
             return HttpResponse.notFound
         }
-        let filePath = dir + "/" + value
+        let filePath = dir + File.PATH_SEPARATOR + value
         do {
             guard try File.exists(filePath) else {
                 return HttpResponse.notFound

+ 8 - 1
Sources/Swifter/HttpRouter.swift

@@ -80,6 +80,13 @@ public class HttpRouter {
     
     private func findHandler(_ node: inout Node, params: inout [String: String], generator: inout IndexingIterator<[String]>) -> ((HttpRequest) -> HttpResponse)? {
         guard let pathToken = generator.next() else {
+            // if it's the last element of the requested URL, check if there is a pattern with variable tail.
+            if let variableNode = node.nodes.filter({ $0.0.characters.first == ":" }).first {
+                if variableNode.value.nodes.isEmpty {
+                    params[variableNode.0] = ""
+                    return variableNode.value.handler
+                }
+            }
             return node.handler
         }
         let variableNodes = node.nodes.filter { $0.0.characters.first == ":" }
@@ -88,7 +95,7 @@ public class HttpRouter {
                 // if it's the last element of the pattern and it's a variable, stop the search and
                 // append a tail as a value for the variable.
                 let tail = generator.joined(separator: "/")
-                if tail.utf8.count > 0 {
+                if tail.characters.count > 0 {
                     params[variableNode.0] = pathToken + "/" + tail
                 } else {
                     params[variableNode.0] = pathToken

+ 23 - 0
XCode/SwifterTestsCommon/SwifterTestsHttpRouter.swift

@@ -82,5 +82,28 @@ class SwifterTestsHttpRouter: XCTestCase {
         XCTAssert(router.route(nil, path: "/a/b/c/d/e/f/g") != nil)
         XCTAssert(router.route(nil, path: "/a/e/f/g") == nil)
     }
+    
+    func testHttpRouterEmptyTail() {
+        
+        let router = HttpRouter()
+        
+        router.register(nil, path: "/a/b/", handler: { r in
+            return .ok(.html("OK"))
+        })
+        
+        router.register(nil, path: "/a/b/:var", handler: { r in
+            return .ok(.html("OK"))
+        })
+
+        
+        XCTAssert(router.route(nil, path: "/") == nil)
+        XCTAssert(router.route(nil, path: "/a") == nil)
+        XCTAssert(router.route(nil, path: "/a/b/") != nil)
+        XCTAssert(router.route(nil, path: "/a/e/f/g") == nil)
+        
+        XCTAssert(router.route(nil, path: "/a/b/value1")?.0[":var"] == "value1")
+        
+        XCTAssert(router.route(nil, path: "/a/b/")?.0[":var"] == "")
+    }
 
 }