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

The value of "Content-Type" header is automatically set for basic response ( .JSON, .XML, .PLST ).
.RAW response allows to modify all fields of the HTTP response (status code, status phrase, headers and body).

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

+ 4 - 1
Common/DemoServer.swift

@@ -53,7 +53,7 @@ func demoServer(publicDir: String?) -> HttpServer {
             case "GET":
                 if let rootDir = publicDir {
                     if let html = NSData(contentsOfFile:"\(rootDir)/login.html") {
-                        return .RAW(200, html)
+                        return HttpResponse.RAW(200, "OK", nil, html)
                     } else {
                         return .NotFound
                     }
@@ -70,6 +70,9 @@ func demoServer(publicDir: String?) -> HttpServer {
         }
         return .NotFound
     }
+    server["/raw"] = { request in
+        return HttpResponse.RAW(200, "OK", ["XXX-Custom-Header": "value"], "Sample Response".dataUsingEncoding(NSUTF8StringEncoding)!)
+    }
     server["/"] = { request in
         var listPage = "Available services:<br><ul>"
         for item in server.routes() {

+ 2 - 2
Common/HttpHandlers.swift

@@ -13,7 +13,7 @@ public class HttpHandlers {
             if let localPath = request.capturedUrlGroups.first {
                 let filesPath = dir.stringByExpandingTildeInPath.stringByAppendingPathComponent(localPath)
                 if let fileBody = NSData(contentsOfFile: filesPath) {
-                    return HttpResponse.RAW(200, fileBody)
+                    return HttpResponse.RAW(200, "OK", nil, fileBody)
                 }
             }
             return HttpResponse.NotFound
@@ -39,7 +39,7 @@ public class HttpHandlers {
                         }
                     } else {
                         if let fileBody = NSData(contentsOfFile: filePath) {
-                            return HttpResponse.RAW(200, fileBody)
+                            return HttpResponse.RAW(200, "OK", nil, fileBody)
                         }
                     }
                 }

+ 38 - 29
Common/HttpResponse.swift

@@ -12,41 +12,41 @@ public enum HttpResponseBody {
     case XML(AnyObject)
     case PLIST(AnyObject)
     case HTML(String)
-    case RAW(String)
+    case STRING(String)
     
-    func data() -> (content: String?, contentType: String?) {
+    func data() -> String? {
         switch self {
         case .JSON(let object):
             if NSJSONSerialization.isValidJSONObject(object) {
                 do {
                     let json = try NSJSONSerialization.dataWithJSONObject(object, options: NSJSONWritingOptions.PrettyPrinted)
                     if let nsString = NSString(data: json, encoding: NSUTF8StringEncoding) {
-                        return (nsString as String, "application/json")
+                        return nsString as String
                     }
                 } catch let serializationError as NSError {
-                    return ("Serialisation error: \(serializationError)", nil)
+                    return "Serialisation error: \(serializationError)"
                 }
             }
-            return ("Invalid object to serialise.", nil)
+            return "Invalid object to serialise."
         case .XML(_):
-            return ("XML serialization not supported.", nil)
+            return "XML serialization not supported."
         case .PLIST(let object):
             let format = NSPropertyListFormat.XMLFormat_v1_0
             if NSPropertyListSerialization.propertyList(object, isValidForFormat: format) {
                 do {
                     let plist = try NSPropertyListSerialization.dataWithPropertyList(object, format: format, options: 0)
                     if let nsString = NSString(data: plist, encoding: NSUTF8StringEncoding) {
-                        return (nsString as String, "application/plist")
+                        return nsString as String
                     }
                 } catch let serializationError as NSError {
-                    return ("Serialisation error: \(serializationError)", nil)
+                    return "Serialisation error: \(serializationError)"
                 }
             }
-            return ("Invalid object to serialise.", nil)
-        case .RAW(let body):
-            return (body, "application/octet-stream")
+            return "Invalid object to serialise."
+        case .STRING(let body):
+            return body
         case .HTML(let body):
-            return ("<html><body>\(body)</body></html>", "text/html")
+            return "<html><body>\(body)</body></html>"
         }
     }
 }
@@ -57,7 +57,7 @@ public enum HttpResponse {
     case MovedPermanently(String)
     case BadRequest, Unauthorized, Forbidden, NotFound
     case InternalServerError
-    case RAW(Int, NSData)
+    case RAW(Int, String, [String:String]?, NSData)
     
     func statusCode() -> Int {
         switch self {
@@ -70,7 +70,7 @@ public enum HttpResponse {
         case .Forbidden             : return 403
         case .NotFound              : return 404
         case .InternalServerError   : return 500
-        case .RAW(let code, _)      : return code
+        case .RAW(let code,_,_,_)   : return code
         }
     }
     
@@ -85,22 +85,34 @@ public enum HttpResponse {
         case .Forbidden             : return "Forbidden"
         case .NotFound              : return "Not Found"
         case .InternalServerError   : return "Internal Server Error"
-        case .RAW(_,_)              : return "Custom"
+        case .RAW(_,let pharse,_,_) : return pharse
         }
     }
     
     func headers() -> [String: String] {
         var headers = [String:String]()
-        headers["Server"] = "Swifter"
+        headers["Server"] = "Swifter \(HttpServer.VERSION)"
         switch self {
 		case .OK(let body):
-			let d = body.data()
-			if let ct = d.1
-			{
-				headers["Content-Type"] = ct
-			}
-			
-        case .MovedPermanently(let location) : headers["Location"] = location
+            switch body {
+                case .JSON(_)   : headers["Content-Type"] = "application/json"
+                case .PLIST(_)  : headers["Content-Type"] = "application/xml"
+                case .XML(_)    : headers["Content-Type"] = "application/xml"
+                // 'application/xml' vs 'text/xml'
+                // From RFC: http://www.rfc-editor.org/rfc/rfc3023.txt - "If an XML document -- that is, the unprocessed, source XML document -- is readable by casual users,
+                // text/xml is preferable to application/xml. MIME user agents (and web user agents) that do not have explicit 
+                // support for text/xml will treat it as text/plain, for example, by displaying the XML MIME entity as plain text. 
+                // Application/xml is preferable when the XML MIME entity is unreadable by casual users."
+                case .HTML(_)   : headers["Content-Type"] = "text/html"
+                default:[]
+            }
+        case .MovedPermanently(let location): headers["Location"] = location
+        case .RAW(_,_, let rawHeaders,_):
+            if let rawHeaders = rawHeaders {
+                for (k, v) in rawHeaders {
+                    headers.updateValue(v, forKey: k)
+                }
+            }
         default:[]
         }
         return headers
@@ -108,12 +120,9 @@ public enum HttpResponse {
     
     func body() -> NSData? {
         switch self {
-        case .OK(let body):
-			let d = body.data()
-			return d.0?.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
-			
-        case .RAW(_, let data)  : return data
-        default                 : return nil
+        case .OK(let body)          : return body.data()?.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
+        case .RAW(_,_,_, let data)  : return data
+        default                     : return nil
         }
     }
 }

+ 3 - 2
Common/HttpServer.swift

@@ -8,6 +8,8 @@ import Foundation
 
 public class HttpServer
 {
+    static let VERSION = "0.9";
+    
     public typealias Handler = HttpRequest -> HttpResponse
     
     var handlers: [(expression: NSRegularExpression, handler: Handler)] = []
@@ -18,8 +20,7 @@ public class HttpServer
     let matchingOptions = NSMatchingOptions(rawValue: 0)
     let expressionOptions = NSRegularExpressionOptions(rawValue: 0)
     
-    public init(){
-    }
+    public init() { }
     
     public subscript (path: String) -> Handler? {
         get {

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


+ 66 - 34
Swifter.xcodeproj/xcuserdata/damiankolakowski.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -202,11 +202,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "44"
-            endingLineNumber = "44"
+            startingLineNumber = "45"
+            endingLineNumber = "45"
             landmarkName = "start(_:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -218,11 +218,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "51"
-            endingLineNumber = "51"
+            startingLineNumber = "52"
+            endingLineNumber = "52"
             landmarkName = "start(_:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -234,11 +234,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "53"
-            endingLineNumber = "53"
+            startingLineNumber = "54"
+            endingLineNumber = "54"
             landmarkName = "start(_:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -250,11 +250,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "55"
-            endingLineNumber = "55"
+            startingLineNumber = "56"
+            endingLineNumber = "56"
             landmarkName = "start(_:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -266,11 +266,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "59"
-            endingLineNumber = "59"
+            startingLineNumber = "60"
+            endingLineNumber = "60"
             landmarkName = "start(_:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -282,11 +282,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "60"
-            endingLineNumber = "60"
+            startingLineNumber = "61"
+            endingLineNumber = "61"
             landmarkName = "start(_:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -314,12 +314,12 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "83"
-            endingLineNumber = "83"
-            landmarkName = "captureExpressionGroups(_:value:)"
+            startingLineNumber = "84"
+            endingLineNumber = "84"
+            landmarkName = "findHandler(_:)"
             landmarkType = "5">
          </BreakpointContent>
       </BreakpointProxy>
@@ -346,11 +346,11 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "56"
-            endingLineNumber = "56"
+            startingLineNumber = "57"
+            endingLineNumber = "57"
             landmarkName = "start(_:error:)"
             landmarkType = "5">
          </BreakpointContent>
@@ -458,12 +458,12 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "116"
-            endingLineNumber = "116"
-            landmarkName = "respond(_:response:keepAlive:)"
+            startingLineNumber = "117"
+            endingLineNumber = "117"
+            landmarkName = "stop()"
             landmarkType = "5">
          </BreakpointContent>
       </BreakpointProxy>
@@ -474,13 +474,13 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "Common/HttpServer.swift"
-            timestampString = "456827105.421335"
+            timestampString = "465835193.153472"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "117"
-            endingLineNumber = "117"
-            landmarkName = "respond(_:response:keepAlive:)"
-            landmarkType = "5">
+            startingLineNumber = "118"
+            endingLineNumber = "118"
+            landmarkName = "HttpServer"
+            landmarkType = "3">
          </BreakpointContent>
       </BreakpointProxy>
       <BreakpointProxy
@@ -878,5 +878,37 @@
             landmarkType = "5">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpResponse.swift"
+            timestampString = "465836128.222429"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "111"
+            endingLineNumber = "111"
+            landmarkName = "headers()"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Common/HttpServer.swift"
+            timestampString = "465836185.461661"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "130"
+            endingLineNumber = "130"
+            landmarkName = "respond(_:response:keepAlive:)"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>