HttpServer.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // HttpServer.swift
  3. //
  4. // Created by Damian Kolakowski on 05/06/14.
  5. // Copyright (c) 2014 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. enum ResponseStatus {
  9. case OK(String)
  10. case NotFound
  11. func numericValue() {
  12. switch self {
  13. case .OK(_):
  14. return 200
  15. case .NotFound:
  16. return 404
  17. }
  18. }
  19. func textValue() {
  20. switch self {
  21. case .OK(let text):
  22. return text
  23. case .NotFound:
  24. return "Not found"
  25. }
  26. }
  27. }
  28. typealias Handler = Void -> ResponseStatus
  29. /* HTTP server */
  30. class HttpServer
  31. {
  32. var handlers = Dictionary<String, Handler>()
  33. var acceptSocket: CInt = -1
  34. subscript (path: String) -> Handler {
  35. get {
  36. return handlers[path]!
  37. }
  38. set ( newValue ) {
  39. self.handlers.updateValue(newValue, forKey: path)
  40. }
  41. }
  42. func start(listenPort: in_port_t) -> (Bool, String?) {
  43. releaseAcceptSocket()
  44. let (socket, error) = Socket.tcpForListen(listenPort)
  45. if ( socket == -1 ) {
  46. return (false, error)
  47. }
  48. acceptSocket = socket
  49. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), { () -> Void in
  50. while ( self.acceptSocket != -1 ) {
  51. var addr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), len: socklen_t = 0
  52. let socket = accept(self.acceptSocket, &addr, &len)
  53. if ( socket == -1 ) {
  54. self.releaseAcceptSocket();
  55. return
  56. }
  57. Socket.nosigpipe(socket)
  58. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), { () -> Void in
  59. let parser = HttpParser()
  60. while let (path, headers) = parser.parseHttpHeader(socket) {
  61. if let handler = self.handlers[path] {
  62. let responseStatus = handler()
  63. let responseText = responseStatus.textValue()
  64. let nsdata =
  65. responseText
  66. .bridgeToObjectiveC()
  67. .dataUsingEncoding(NSUTF8StringEncoding)
  68. Socket.writeStringUTF8(socket, string: "HTTP/1.1 \(responseStatus.numericValue())\r\n")
  69. Socket.writeStringUTF8(socket, string: "Content-Length: \(nsdata.length)\r\n")
  70. if parser.supportsKeepAlive(headers) {
  71. Socket.writeStringUTF8(socket, string: "Connection: keep-alive\r\n")
  72. }
  73. Socket.writeStringUTF8(socket, string: "\r\n")
  74. Socket.writeStringUTF8(socket, string: responseText)
  75. } else {
  76. Socket.writeStringUTF8(socket, string: "HTTP/1.1 \(ResponseStatus.NotFound.numericValue())\r\n")
  77. Socket.writeStringUTF8(socket, string: "Content-Length: 0\r\n")
  78. if parser.supportsKeepAlive(headers) {
  79. Socket.writeStringUTF8(socket, string: "Connection: keep-alive\r\n")
  80. }
  81. Socket.writeStringUTF8(socket, string: "\r\n")
  82. }
  83. if !parser.supportsKeepAlive(headers) {
  84. break
  85. }
  86. }
  87. Socket.release(socket)
  88. });
  89. }
  90. });
  91. return (true, nil)
  92. }
  93. func stop() {
  94. releaseAcceptSocket()
  95. }
  96. func releaseAcceptSocket() {
  97. if ( acceptSocket != -1 ) {
  98. Socket.release(acceptSocket)
  99. acceptSocket = -1
  100. }
  101. }
  102. }