فهرست منبع

Stable branch uses sendfile for serving static files.
More Scopes DSL in the demo server.

Damian Kołakowski 10 سال پیش
والد
کامیت
51ce7fa862

+ 0 - 11
Resources/file.html

@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-	<body>
-        <form method="POST" action="/upload" 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</button>
-        </form>
-	</body>
-</html>

+ 0 - 35
Resources/login.html

@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html>
-  	<head>
-		<link rel="shortcut icon" href="/static/img/favicon.png" />
-    	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-		<link href="http://cdn.staticfile.org/twitter-bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" />
-		<script src="http://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>
-    	<title>Login</title>
-  	</head>
-	<body>
-        <div class="col-md-12">
-            <div class="modal-dialog" style="margin-bottom:0">
-                <div class="modal-content">
-                    <div class="panel-heading">
-                        <h3 class="panel-title">Sign In</h3>
-                    </div>
-                    <div class="panel-body">
-                        <form role="form" method="POST" action="/login">
-                            <fieldset>
-                                <div class="form-group">
-                                    <input class="form-control" placeholder="E-mail" name="email" type="email" autofocus="">
-                                </div>
-                                <div class="form-group">
-                                    <input class="form-control" placeholder="Password" name="password" type="password" value="">
-                                </div>
-                                <a href="/login"><button type="submit" class="btn btn-default">Login</button></a>
-                            </fieldset>
-                        </form>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <script type="text/javascript" src="http://cdn.staticfile.org/twitter-bootstrap/3.3.0/js/bootstrap.min.js"></script>
-	</body>
-</html>

+ 0 - 3
Resources/test.json

@@ -1,3 +0,0 @@
-{
-    "test" : "test"
-}

+ 87 - 27
Sources/DemoServer.swift

@@ -18,7 +18,7 @@ public func demoServer(publicDir: String) -> HttpServer {
 
     server["/files/:path"] = HttpHandlers.directoryBrowser("/")
 
-    server["/"] = HttpHandlers.scopes {
+    server["/"] = scopes {
         html {
             body {
                 ul(server.routes) { service in
@@ -33,28 +33,63 @@ public func demoServer(publicDir: String) -> HttpServer {
     server["/magic"] = { .OK(.Html("You asked for " + $0.path)) }
     
     server["/test/:param1/:param2"] = { r in
-        var headersInfo = ""
-        for (name, value) in r.headers {
-            headersInfo += "\(name) : \(value)<br>"
-        }
-        var queryParamsInfo = ""
-        for (name, value) in r.queryParams {
-            queryParamsInfo += "\(name) : \(value)<br>"
-        }
-        var pathParamsInfo = ""
-        for token in r.params {
-            pathParamsInfo += "\(token.0) : \(token.1)<br>"
-        }
-        return .OK(.Html("<h3>Address: \(r.address)</h3><h3>Url:</h3> \(r.path)<h3>Method:</h3>\(r.method)<h3>Headers:</h3>\(headersInfo)<h3>Query:</h3>\(queryParamsInfo)<h3>Path params:</h3>\(pathParamsInfo)"))
+        scopes {
+            html {
+                body {
+                    h3 { inner = "Address: \(r.address)" }
+                    h3 { inner = "Url: \(r.path)" }
+                    h3 { inner = "Method: \(r.method)" }
+                    
+                    h3 { inner = "Query:" }
+                    
+                    table(r.queryParams) { param in
+                        tr {
+                            td { inner = param.0 }
+                            td { inner = param.1 }
+                        }
+                    }
+                    
+                    h3 { inner = "Headers:" }
+                    
+                    table(r.headers) { header in
+                        tr {
+                            td { inner = header.0 }
+                            td { inner = header.1 }
+                        }
+                    }
+                    
+                    h3 { inner = "Route params:" }
+                    
+                    table(r.params) { param in
+                        tr {
+                            td { inner = param.0 }
+                            td { inner = param.1 }
+                        }
+                    }
+                }
+            }
+        }(r)
     }
     
-    server.GET["/upload"] = { r in
-        if let html = NSData(contentsOfFile:"\(publicDir)/file.html") {
-            var array = [UInt8](count: html.length, repeatedValue: 0)
-            html.getBytes(&array, length: html.length)
-            return HttpResponse.RAW(200, "OK", nil, { $0.write(array) })
+    server.GET["/upload"] = scopes {
+        html {
+            body {
+                form {
+                    method = "POST"
+                    action = "/upload"
+                    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"
+                        inner = "Upload"
+                    }
+                }
+            }
         }
-        return .NotFound
     }
     
     server.POST["/upload"] = { r in
@@ -65,13 +100,37 @@ public func demoServer(publicDir: String) -> HttpServer {
         return HttpResponse.OK(.Html(response))
     }
     
-    server.GET["/login"] = { r in
-        if let html = NSData(contentsOfFile:"\(publicDir)/login.html") {
-            var array = [UInt8](count: html.length, repeatedValue: 0)
-            html.getBytes(&array, length: html.length)
-            return HttpResponse.RAW(200, "OK", nil, { $0.write(array) })
+    server.GET["/login"] = scopes {
+        html {
+            head {
+                script { src = "http://cdn.staticfile.org/jquery/2.1.4/jquery.min.js" }
+                stylesheet { href = "http://cdn.staticfile.org/twitter-bootstrap/3.3.0/css/bootstrap.min.css" }
+            }
+            body {
+                h3 { inner = "Sign In" }
+                
+                form {
+                    method = "POST"
+                    action = "/login"
+                    
+                    fieldset {
+                        input { placeholder = "E-mail"; name = "email"; type = "email"; autofocus = "" }
+                        input { placeholder = "Password"; name = "password"; type = "password"; autofocus = "" }
+                        a {
+                            href = "/login"
+                            button {
+                                type = "submit"
+                                inner = "Login"
+                            }
+                        }
+                    }
+                    
+                }
+                javascript {
+                    src = "http://cdn.staticfile.org/twitter-bootstrap/3.3.0/js/bootstrap.min.js"
+                }
+            }
         }
-        return .NotFound
     }
     
     server.POST["/login"] = { r in
@@ -79,7 +138,7 @@ public func demoServer(publicDir: String) -> HttpServer {
         return HttpResponse.OK(.Html(formFields.map({ "\($0.0) = \($0.1)" }).joinWithSeparator("<br>")))
     }
     
-    server["/demo"] = HttpHandlers.scopes {
+    server["/demo"] = scopes {
         html {
             body {
                 center {
@@ -138,3 +197,4 @@ public func demoServer(publicDir: String) -> HttpServer {
     
     return server
 }
+    

+ 40 - 1
Sources/File.swift

@@ -17,6 +17,8 @@ public enum FileError: ErrorType {
     case ReadFailed(String)
     case SeekFailed(String)
     case GetCurrentWorkingDirectoryFailed(String)
+    case IsDirectoryFailed(String)
+    case OpenDirFailed(String)
 }
 
 public class File {
@@ -41,6 +43,14 @@ public class File {
         return File(file)
     }
     
+    public static func isDirectory(path: String) throws -> Bool {
+        var s = stat()
+        guard path.withCString({ stat($0, &s) }) == 0 else {
+            throw FileError.IsDirectoryFailed(descriptionOfLastError())
+        }
+        return s.st_mode & S_IFMT == S_IFDIR
+    }
+    
     public static func currentWorkingDirectory() throws -> String {
         let path = getcwd(nil, 0)
         if path == nil {
@@ -52,7 +62,36 @@ public class File {
         return result
     }
     
-    private let pointer: UnsafeMutablePointer<FILE>
+    public static func exists(path: String) throws -> Bool {
+        var buffer = stat()
+        return path.withCString({ stat($0, &buffer) == 0 })
+    }
+    
+    public static func list(path: String) throws -> [String] {
+        let dir = path.withCString { opendir($0) }
+        if dir == nil {
+            throw FileError.OpenDirFailed(descriptionOfLastError())
+        }
+        defer { closedir(dir) }
+        var results = [String]()
+        while true {
+            let ent = readdir(dir)
+            if ent == nil {
+                break
+            }
+            let fileName = withUnsafePointer(&ent.memory.d_name) { (ptr) -> String? in
+                var buffer = [CChar](UnsafeBufferPointer(start: unsafeBitCast(ptr, UnsafePointer<CChar>.self), count: Int(ent.memory.d_namlen)))
+                buffer.append(0)
+                return String.fromCString(buffer)
+            }
+            if let fileName = fileName {
+                results.append(fileName)
+            }
+        }
+        return results
+    }
+    
+    let pointer: UnsafeMutablePointer<FILE>
     
     public init(_ pointer: UnsafeMutablePointer<FILE>) {
         self.pointer = pointer

+ 34 - 26
Sources/HttpHandlers+Files.swift

@@ -9,20 +9,17 @@ import Foundation
 
 extension HttpHandlers {
     
-    public class func shareFilesFromDirectory(directoryPath: String, chunkSize: Int = 64) -> (HttpRequest -> HttpResponse) {
+    public class func shareFilesFromDirectory(directoryPath: String) -> (HttpRequest -> HttpResponse) {
         return { r in
-            guard let absolutePath = self.fileNameToShare(directoryPath, request: r) else {
+            guard let fileRelativePath = r.params.first else {
                 return .NotFound
             }
-
+            let absolutePath = directoryPath + "/" + fileRelativePath.1
             guard let file = try? File.openForReading(absolutePath) else {
                 return .NotFound
             }
             return .RAW(200, "OK", [:], { writer in
-                var buffer = [UInt8](count: chunkSize, repeatedValue: 0)
-                while let count = try? file.read(&buffer) where count > 0 {
-                    writer.write(buffer[0 ..< count])
-                }
+                writer.write(file)
                 file.close()
             })
         }
@@ -124,28 +121,39 @@ extension HttpHandlers {
                 return HttpResponse.NotFound
             }
             let filePath = dir + "/" + value
-            let fileManager = NSFileManager.defaultManager()
-            var isDir: ObjCBool = false
-            guard fileManager.fileExistsAtPath(filePath, isDirectory: &isDir) else {
-                return HttpResponse.NotFound
-            }
-            if isDir {
-                do {
-                    let files = try fileManager.contentsOfDirectoryAtPath(filePath)
-                    var response = "<h3>\(filePath)</h3></br><table>"
-                    response += files.map({ "<tr><td><a href=\"\(r.path)/\($0)\">\($0)</a></td></tr>"}).joinWithSeparator("")
-                    response += "</table>"
-                    return HttpResponse.OK(.Html(response))
-                } catch {
+            do {
+                guard try File.exists(filePath) else {
                     return HttpResponse.NotFound
                 }
-            } else {
-                if let content = NSData(contentsOfFile: filePath) {
-                    var array = [UInt8](count: content.length, repeatedValue: 0)
-                    content.getBytes(&array, length: content.length)
-                    return HttpResponse.RAW(200, "OK", nil, { $0.write(array) })
+                if try File.isDirectory(filePath) {
+                    let files = try File.list(filePath)
+                    return scopes {
+                        html {
+                            body {
+                                table(files) { file in
+                                    tr {
+                                        td {
+                                            a {
+                                                href = r.path + "/" + file
+                                                inner = file
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }(r)
+                } else {
+                    guard let file = try? File.openForReading(filePath) else {
+                        return .NotFound
+                    }
+                    return .RAW(200, "OK", [:], { writer in
+                        writer.write(file)
+                        file.close()
+                    })
                 }
-                return HttpResponse.NotFound
+            } catch {
+                return HttpResponse.InternalServerError
             }
         }
     }

+ 13 - 10
Sources/HttpHandlers+Scopes.swift

@@ -7,15 +7,12 @@
 
 import Foundation
 
-extension HttpHandlers {
-    
-    public class func scopes(c: Closure) -> ((HttpRequest) -> HttpResponse) {
-        return { r in
-            ScopesBuffer[Process.TID] = ""
-            c()
-            return .RAW(200, "OK", ["Content-Type": "text/html"],
-                        { $0.write([UInt8](("<!DOCTYPE html>"  + (ScopesBuffer[Process.TID] ?? "")).utf8)) })
-        }
+public func scopes(scope: Closure) -> ((HttpRequest) -> HttpResponse) {
+    return { r in
+        ScopesBuffer[Process.TID] = ""
+        scope()
+        return .RAW(200, "OK", ["Content-Type": "text/html"],
+                    { $0.write([UInt8](("<!DOCTYPE html>"  + (ScopesBuffer[Process.TID] ?? "")).utf8)) })
     }
 }
 
@@ -127,6 +124,7 @@ public var maxlength: String? = nil
 public var valuetype: String? = nil
 public var accesskey: String? = nil
 public var onmouseup: String? = nil
+public var autofocus: String? = nil
 public var onkeypress: String? = nil
 public var ondblclick: String? = nil
 public var onmouseout: String? = nil
@@ -139,6 +137,7 @@ public var onmousedown: String? = nil
 public var frameborder: String? = nil
 public var marginwidth: String? = nil
 public var cellspacing: String? = nil
+public var placeholder: String? = nil
 public var marginheight: String? = nil
 public var acceptCharset: String? = nil
 
@@ -320,7 +319,7 @@ public func template(c: Closure) { element("template", c) }
 public func textarea(c: Closure) { element("textarea", c) }
 
 public func plaintext(c: Closure) { element("plaintext", c) }
-
+public func javascript(c: Closure) { element("script", ["type": "text/javascript"], c) }
 public func blockquote(c: Closure) { element("blockquote", c) }
 public func figcaption(c: Closure) { element("figcaption", c) }
 
@@ -453,6 +452,7 @@ private func evaluate(node: String, _ attrs: [String: String?] = [:], _ c: Closu
     let stackframeborder = frameborder
     let stackmarginwidth = marginwidth
     let stackcellspacing = cellspacing
+    let stackplaceholder = placeholder
     let stackmarginheight = marginheight
     let stackacceptCharset = acceptCharset
     let stackinner = inner
@@ -575,6 +575,7 @@ private func evaluate(node: String, _ attrs: [String: String?] = [:], _ c: Closu
     cellpadding = nil
     onmousedown = nil
     frameborder = nil
+    placeholder = nil
     marginwidth = nil
     cellspacing = nil
     marginheight = nil
@@ -717,6 +718,7 @@ private func evaluate(node: String, _ attrs: [String: String?] = [:], _ c: Closu
     if let frameborder = frameborder { mergedAttributes["frameborder"] = frameborder }
     if let marginwidth = marginwidth { mergedAttributes["marginwidth"] = marginwidth }
     if let cellspacing = cellspacing { mergedAttributes["cellspacing"] = cellspacing }
+    if let placeholder = placeholder { mergedAttributes["placeholder"] = placeholder }
     if let marginheight = marginheight { mergedAttributes["marginheight"] = marginheight }
     if let acceptCharset = acceptCharset { mergedAttributes["accept-charset"] = acceptCharset }
     
@@ -857,6 +859,7 @@ private func evaluate(node: String, _ attrs: [String: String?] = [:], _ c: Closu
     cellpadding = stackcellpadding
     onmousedown = stackonmousedown
     frameborder = stackframeborder
+    placeholder = stackplaceholder
     marginwidth = stackmarginwidth
     cellspacing = stackcellspacing
     marginheight = stackmarginheight

+ 1 - 0
Sources/HttpResponse.swift

@@ -17,6 +17,7 @@ public enum SerializationError: ErrorType {
 }
 
 public protocol HttpResponseBodyWriter {
+    func write(file: File)
     func write(data: [UInt8])
     func write(data: ArraySlice<UInt8>)
 }

+ 27 - 0
Sources/HttpServerIO.swift

@@ -83,9 +83,16 @@ public class HttpServerIO {
     
     private struct InnerWriteContext: HttpResponseBodyWriter {
         let socket: Socket
+        
+        func write(file: File) {
+            var offset: off_t = 0
+            let _ = sendfile(fileno(file.pointer), socket.socketFileDescriptor, 0, &offset, nil, 0)
+        }
+
         func write(data: [UInt8]) {
             write(ArraySlice(data))
         }
+        
         func write(data: ArraySlice<UInt8>) {
             do {
                 try socket.writeUInt8(data)
@@ -126,6 +133,26 @@ public class HttpServerIO {
 #if os(Linux)
     
     import Glibc
+    
+    struct sf_hdtr { }
+    
+    func sendfile(source: Int32, _ target: Int32, _: off_t, _: UnsafeMutablePointer<off_t>!, _: UnsafeMutablePointer<sf_hdtr>!, _: Int32) -> Int32 {
+        var buffer = [UInt8](repeating: 0, count: 1024)
+        while true {
+            let readResult = read(source, &buffer, buffer.count)
+            guard readResult > 0 else {
+                return Int32(readResult)
+            }
+            var writeCounter = 0
+            while writeCounter < readResult {
+                let writeResult = write(target, &buffer + writeCounter, readResult - writeCounter)
+                guard writeResult > 0 else {
+                    return Int32(writeResult)
+                }
+                writeCounter = writeCounter + writeResult
+            }
+        }
+    }
 
     public class NSLock {
     

+ 1 - 1
Sources/Socket.swift

@@ -102,7 +102,7 @@ public class Socket: Hashable, Equatable {
         return Socket(socketFileDescriptor: socketFileDescriptor)
     }
     
-    private let socketFileDescriptor: Int32
+    let socketFileDescriptor: Int32
     
     public init(socketFileDescriptor: Int32) {
         self.socketFileDescriptor = socketFileDescriptor

+ 0 - 18
Swifter.xcodeproj/project.pbxproj

@@ -17,7 +17,6 @@
 		7C2BEC7A1C5195F200B8EE90 /* String+SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2BEC771C518B7C00B8EE90 /* String+SHA1.swift */; };
 		7C4785E91C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */; };
 		7C4785EA1C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */; };
-		7C71C5B01A1D52F800682BF0 /* login.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
 		7C71C5B11A1EC49B00682BF0 /* logo.png in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CB102DF1A17381D00CBA3B4 /* logo.png */; };
 		7C73C6911C2615FE00AEF6CA /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18E610A51BD6397D00B7D17A /* SwiftyJSON.swift */; };
 		7C73C6921C26179C00AEF6CA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDAB80C1BE2A1D400C8A977 /* AppDelegate.swift */; };
@@ -41,8 +40,6 @@
 		7C73C6BC1C261A2600AEF6CA /* HttpServerIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C73C69B1C2619E100AEF6CA /* HttpServerIO.swift */; };
 		7C73C6BD1C261A2600AEF6CA /* Socket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C73C69C1C2619E100AEF6CA /* Socket.swift */; };
 		7C73C6BE1C261A2600AEF6CA /* String+Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C73C69D1C2619E100AEF6CA /* String+Misc.swift */; };
-		7C7488781C1DA07300CBCD77 /* file.html in Resources */ = {isa = PBXBuildFile; fileRef = 7C7488771C1DA07300CBCD77 /* file.html */; };
-		7C74887B1C1DA08200CBCD77 /* file.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7C7488771C1DA07300CBCD77 /* file.html */; };
 		7C76B6DE1D2BB1050030FC98 /* HttpHandlers+Scopes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6DD1D2BB1050030FC98 /* HttpHandlers+Scopes.swift */; };
 		7C76B6DF1D2BB1050030FC98 /* HttpHandlers+Scopes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6DD1D2BB1050030FC98 /* HttpHandlers+Scopes.swift */; };
 		7C76B6E01D2BB1050030FC98 /* HttpHandlers+Scopes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6DD1D2BB1050030FC98 /* HttpHandlers+Scopes.swift */; };
@@ -52,8 +49,6 @@
 		7C76B6E51D2BB1320030FC98 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6E21D2BB1320030FC98 /* Process.swift */; };
 		7C76B6E61D2BB1320030FC98 /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6E21D2BB1320030FC98 /* Process.swift */; };
 		7CA4813E19A2EA8D0030B30D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CA4813D19A2EA8D0030B30D /* main.swift */; };
-		7CA4815819A2EF2B0030B30D /* test.json in Resources */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
-		7CA4815919A2EF560030B30D /* test.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CB102E01A17381D00CBA3B4 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 7CB102DF1A17381D00CBA3B4 /* logo.png */; };
 		7CC0F8C91C50136B00B65A94 /* HttpHandlers+Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0F8C81C50136B00B65A94 /* HttpHandlers+Files.swift */; };
 		7CC0F8CA1C50136B00B65A94 /* HttpHandlers+Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0F8C81C50136B00B65A94 /* HttpHandlers+Files.swift */; };
@@ -70,7 +65,6 @@
 		7CDAB8131BE2A1D400C8A977 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80D1BE2A1D400C8A977 /* Main.storyboard */; };
 		7CDAB8141BE2A1D400C8A977 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */; };
 		7CDAB8161BE2A1D400C8A977 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDAB8111BE2A1D400C8A977 /* ViewController.swift */; };
-		98630C071A1C9A9D00478D08 /* login.html in Resources */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -111,10 +105,7 @@
 			dstPath = "";
 			dstSubfolderSpec = 7;
 			files = (
-				7C74887B1C1DA08200CBCD77 /* file.html in CopyFiles */,
 				7C71C5B11A1EC49B00682BF0 /* logo.png in CopyFiles */,
-				7C71C5B01A1D52F800682BF0 /* login.html in CopyFiles */,
-				7CA4815919A2EF560030B30D /* test.json in CopyFiles */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -142,13 +133,11 @@
 		7C73C69B1C2619E100AEF6CA /* HttpServerIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpServerIO.swift; sourceTree = "<group>"; };
 		7C73C69C1C2619E100AEF6CA /* Socket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Socket.swift; sourceTree = "<group>"; };
 		7C73C69D1C2619E100AEF6CA /* String+Misc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Misc.swift"; sourceTree = "<group>"; };
-		7C7488771C1DA07300CBCD77 /* file.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = file.html; sourceTree = "<group>"; };
 		7C76B6DD1D2BB1050030FC98 /* HttpHandlers+Scopes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HttpHandlers+Scopes.swift"; sourceTree = "<group>"; };
 		7C76B6E21D2BB1320030FC98 /* Process.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Process.swift; sourceTree = "<group>"; };
 		7C839B6E19422CFF003A6950 /* SwifterSampleiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwifterSampleiOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		7CA4813B19A2EA8D0030B30D /* SwifterSampleOSX */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SwifterSampleOSX; sourceTree = BUILT_PRODUCTS_DIR; };
 		7CA4813D19A2EA8D0030B30D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
-		7CA4815719A2EF2B0030B30D /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = "<group>"; };
 		7CB102DF1A17381D00CBA3B4 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = "<group>"; };
 		7CC0F8C81C50136B00B65A94 /* HttpHandlers+Files.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HttpHandlers+Files.swift"; sourceTree = "<group>"; };
 		7CC0F8CB1C5014A200B65A94 /* HttpHandlers+WebSockets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HttpHandlers+WebSockets.swift"; sourceTree = "<group>"; };
@@ -165,7 +154,6 @@
 		7CDAB8101BE2A1D400C8A977 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		7CDAB8111BE2A1D400C8A977 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
 		7CEAF86F1C14B2B5003252DE /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
-		98630C061A1C9A9D00478D08 /* login.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = login.html; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -276,10 +264,7 @@
 		7CA4815619A2EF2B0030B30D /* Resources */ = {
 			isa = PBXGroup;
 			children = (
-				7C7488771C1DA07300CBCD77 /* file.html */,
-				98630C061A1C9A9D00478D08 /* login.html */,
 				7CB102DF1A17381D00CBA3B4 /* logo.png */,
-				7CA4815719A2EF2B0030B30D /* test.json */,
 			);
 			path = Resources;
 			sourceTree = "<group>";
@@ -549,12 +534,9 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				7C7488781C1DA07300CBCD77 /* file.html in Resources */,
 				7AE8940D1C05151100A29F63 /* Launch Screen.storyboard in Resources */,
 				7CB102E01A17381D00CBA3B4 /* logo.png in Resources */,
 				7CDAB8141BE2A1D400C8A977 /* Images.xcassets in Resources */,
-				98630C071A1C9A9D00478D08 /* login.html in Resources */,
-				7CA4815819A2EF2B0030B30D /* test.json in Resources */,
 				7CDAB8131BE2A1D400C8A977 /* Main.storyboard in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;