1
0

HttpResponse.swift 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. //
  2. // HttpResponse.swift
  3. // Swifter
  4. //
  5. // Copyright (c) 2014-2016 Damian Kołakowski. All rights reserved.
  6. //
  7. #if os(Linux)
  8. import Glibc
  9. #else
  10. import Foundation
  11. #endif
  12. public enum SerializationError: ErrorType {
  13. case InvalidObject
  14. case NotSupported
  15. }
  16. public protocol HttpResponseBodyWriter {
  17. func write(file: File) throws
  18. func write(data: [UInt8]) throws
  19. func write(data: ArraySlice<UInt8>) throws
  20. }
  21. public enum HttpResponseBody {
  22. case Json(AnyObject)
  23. case Html(String)
  24. case Text(String)
  25. case Custom(AnyObject, (Any) throws -> String)
  26. func content() -> (Int, (HttpResponseBodyWriter throws -> Void)?) {
  27. do {
  28. print(String(self))
  29. let response: ResponseProtocol;
  30. switch self {
  31. case .Json(let object):
  32. let response = JsonResponse(contentObject: object)
  33. case .Text(let body):
  34. let response = TextResponse(contentObject: object!)
  35. case .Html(let body):
  36. let response = HtmlResponse(contentObject: object!)
  37. case .Custom(let object, let closure):
  38. let response = CustomResponse(contentObject: object, closure: closure)
  39. default:
  40. let response = Response(contentObject: "")
  41. }
  42. let content = response.content()
  43. return (content.contentLength, {
  44. try $0.write(content)
  45. })
  46. } catch {
  47. let data = [UInt8]("Serialisation error: \(error)".utf8)
  48. return (data.count, {
  49. try $0.write(data)
  50. })
  51. }
  52. }
  53. }
  54. public enum HttpResponse {
  55. case SwitchProtocols([String: String], Socket -> Void)
  56. case OK(HttpResponseBody), Created, Accepted
  57. case MovedPermanently(String)
  58. case BadRequest(HttpResponseBody?), Unauthorized, Forbidden, NotFound
  59. case InternalServerError
  60. case RAW(Int, String, [String:String]?, (HttpResponseBodyWriter throws -> Void)? )
  61. func statusCode() -> Int {
  62. switch self {
  63. case .SwitchProtocols(_, _) : return 101
  64. case .OK(_) : return 200
  65. case .Created : return 201
  66. case .Accepted : return 202
  67. case .MovedPermanently : return 301
  68. case .BadRequest(_) : return 400
  69. case .Unauthorized : return 401
  70. case .Forbidden : return 403
  71. case .NotFound : return 404
  72. case .InternalServerError : return 500
  73. case .RAW(let code, _ , _, _) : return code
  74. }
  75. }
  76. func reasonPhrase() -> String {
  77. switch self {
  78. case .SwitchProtocols(_, _) : return "Switching Protocols"
  79. case .OK(_) : return "OK"
  80. case .Created : return "Created"
  81. case .Accepted : return "Accepted"
  82. case .MovedPermanently : return "Moved Permanently"
  83. case .BadRequest(_) : return "Bad Request"
  84. case .Unauthorized : return "Unauthorized"
  85. case .Forbidden : return "Forbidden"
  86. case .NotFound : return "Not Found"
  87. case .InternalServerError : return "Internal Server Error"
  88. case .RAW(_, let phrase, _, _) : return phrase
  89. }
  90. }
  91. func headers() -> [String: String] {
  92. var headers = ["Server" : "Swifter \(HttpServer.VERSION)"]
  93. switch self {
  94. case .SwitchProtocols(let switchHeaders, _):
  95. for (key, value) in switchHeaders {
  96. headers[key] = value
  97. }
  98. case .OK(let body):
  99. switch body {
  100. case .Json(_) : headers["Content-Type"] = "application/json"
  101. case .Html(_) : headers["Content-Type"] = "text/html"
  102. default:break
  103. }
  104. case .MovedPermanently(let location):
  105. headers["Location"] = location
  106. case .RAW(_, _, let rawHeaders, _):
  107. if let rawHeaders = rawHeaders {
  108. for (k, v) in rawHeaders {
  109. headers.updateValue(v, forKey: k)
  110. }
  111. }
  112. default:break
  113. }
  114. return headers
  115. }
  116. func content() -> (length: Int, write: (HttpResponseBodyWriter throws -> Void)?) {
  117. switch self {
  118. case .OK(let body) : return body.content()
  119. case .BadRequest(let body) : return body?.content() ?? (-1, nil)
  120. case .RAW(_, _, _, let writer) : return (-1, writer)
  121. default : return (-1, nil)
  122. }
  123. }
  124. func socketSession() -> (Socket -> Void)? {
  125. switch self {
  126. case SwitchProtocols(_, let handler) : return handler
  127. default: return nil
  128. }
  129. }
  130. }
  131. /**
  132. Makes it possible to compare handler responses with '==', but
  133. ignores any associated values. This should generally be what
  134. you want. E.g.:
  135. let resp = handler(updatedRequest)
  136. if resp == .NotFound {
  137. print("Client requested not found: \(request.url)")
  138. }
  139. */
  140. func ==(inLeft: HttpResponse, inRight: HttpResponse) -> Bool {
  141. return inLeft.statusCode() == inRight.statusCode()
  142. }