Răsfoiți Sursa

More demo examples at main.swift.

Damian Kołakowski 9 ani în urmă
părinte
comite
df4353719f
3 a modificat fișierele cu 95 adăugiri și 31 ștergeri
  1. 54 22
      Sources/Files.swift
  2. 2 2
      Sources/String+File.swift
  3. 39 7
      XCode/SwifterSampleOSX/main.swift

+ 54 - 22
Sources/Files.swift

@@ -6,8 +6,9 @@
 //
 
 import Foundation
+
 /*
-public func shareFile(_ path: String) -> ((HttpRequest) -> HttpResponse) {
+public func shareFile(_ path: String) {
     return { r in
         if let file = try? path.openForReading() {
             return .raw(200, "OK", [:], { writer in
@@ -17,34 +18,65 @@ public func shareFile(_ path: String) -> ((HttpRequest) -> HttpResponse) {
         }
         return .notFound
     }
-}
+}*/
 
-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
+#if os(iOS) || os(Linux)
+    
+func fileZeroCopy(from: Int32, to: Int32) {
+    var buffer = [UInt8](repeating: 0, count: 1024)
+    while true {
+        let readResult = read(source, &buffer, buffer.count)
+        guard readResult > 0 else {
+            return Int32(readResult)
         }
-        if fileRelativePath.value.isEmpty {
-            for path in defaults {
-                if let file = try? (directoryPath + String.pathSeparator + path).openForReading() {
-                    return .raw(200, "OK", [:], { writer in
-                        try? writer.write(file)
-                        file.close()
-                    })
-                }
+        var writeCounter = 0
+        while writeCounter < readResult {
+            let writeResult = write(target, &buffer + writeCounter, readResult - writeCounter)
+            guard writeResult > 0 else {
+                return Int32(writeResult)
             }
+            writeCounter = writeCounter + writeResult
         }
-        if let file = try? (directoryPath + String.pathSeparator + fileRelativePath.value).openForReading() {
-            return .raw(200, "OK", [:], { writer in
-                try? writer.write(file)
-                file.close()
-            })
-        }
-        return .notFound
     }
 }
 
-public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) {
+#else
+
+func fileZeroCopy(from: Int32, to: Int32) {
+    var offset: off_t = 0
+    var sf: sf_hdtr = sf_hdtr()
+    sendfile(from, to, 0, &offset, &sf, 0)
+}
+
+#endif
+
+@available(OSXApplicationExtension 10.10, *)
+public func share(filesAtPath path: String, defaults: [String] = ["index.html", "default.html"]) -> (([String: String], Request, @escaping ((Response) -> Void)) -> Void) {
+        return { (params, request, responder) in
+            DispatchQueue.global(qos: .background).async {
+                guard let fileRelativePath = params.first else {
+                    return responder(404)
+                }
+                if fileRelativePath.value.isEmpty {
+                    for path in defaults {
+                        if let file = try? (path + String.pathSeparator + path).openFile(forMode: "r+b") {
+                            fileZeroCopy(from: fileno(file.pointer), to: 0)
+                            file.close()
+                        }
+                    }
+                }
+                if let file = try? (path + String.pathSeparator + fileRelativePath.value).openFile(forMode: "r+b") {
+                    fileZeroCopy(from: fileno(file.pointer), to: 0)
+                    file.close()
+                }
+                return responder(404)
+            }
+        }
+}
+
+/*
+
+public func directoryBrowser(_ dir: String) -> (([String: String], Request, @escaping ((Response) -> Void)) -> Void) {
     return { r in
         guard let (_, value) = r.params.first else {
             return HttpResponse.notFound

+ 2 - 2
Sources/String+File.swift

@@ -64,8 +64,8 @@ extension String {
     
     public static var pathSeparator = "/"
     
-    public func openFile(_ path: String, _ mode: String) throws -> File {
-        guard let file = path.withCString({ pathPointer in mode.withCString({ fopen(pathPointer, $0) }) }) else {
+    public func openFile(forMode mode: String) throws -> File {
+        guard let file = self.withCString({ pathPointer in mode.withCString({ fopen(pathPointer, $0) }) }) else {
             throw FileError.error(errno)
         }
         return File(file)

+ 39 - 7
XCode/SwifterSampleOSX/main.swift

@@ -7,6 +7,7 @@
 import Foundation
 import Swifter
 
+
 let server = try Swifter()
 
 server.get("/") { _, request, responder in
@@ -21,7 +22,7 @@ server.get("/hello") { _, _, responder in
     responder(200)
 }
 
-server.get("/stream") { _, request, responder in
+server.get("/test/websocket") { _, request, responder in
     responder(WebsocketResponse(request) { event in
         switch event {
             case .text(let value):
@@ -34,7 +35,7 @@ server.get("/stream") { _, request, responder in
     })
 }
 
-server.get("/background") { _, _, closure in
+server.get("/test/background") { _, _, closure in
     
     if #available(OSXApplicationExtension 10.10, *) {
         DispatchQueue.global(qos: .background).async {
@@ -48,22 +49,53 @@ server.get("/background") { _, _, closure in
     
 }
 
-server.post("/post") { _, request, responder in
+server.get("/test/multipart") { _, request, responder in
     
-    let post = request.parseUrlencodedForm()
+    responder(html(200) {
+        "body" ~ {
+            "form(method=POST,action=/test/multipart,enctype=multipart/form-data)" ~ {
+
+                "input(name=my_file1,type=file)" ~ ""
+                "input(name=my_file2,type=file)" ~ ""
+                "input(name=my_file3,type=file)" ~ ""
+
+                "button(type=submit)" ~ "Upload"
+            }
+        }
+    })
+}
+
+server.post("/test/multipart") { _, request, responder in
+    
+    let multiparts = request.parseMultiPartFormData()
     
     responder(html(200) {
         "body" ~ {
-            "h4" ~ "You sent: "
+            "h5" ~ "Parts"
             "ul" ~ {
-                post.forEach { item in
-                    "li" ~ "\(item.0) -> \(item.1)"
+                multiparts.forEach { part in
+                    "li" ~ "\(part.fileName) -- \(part.body.count)"
                 }
             }
         }
     })
 }
 
+server.notFoundHandler = { r in
+    return html(200) {
+        "body" ~ {
+            "h5" ~ "Page not found. Try:"
+            "ul" ~ {
+                server.routes.forEach { route in
+                    "li" ~ {
+                        "a(href=\(route))" ~ route
+                    }
+                }
+            }
+        }
+    }
+}
+
 while true {
     try server.loop()
 }