HttpParser.swift 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. //
  2. // HttpParser.swift
  3. // Swifter
  4. // Copyright (c) 2015 Damian Kołakowski. All rights reserved.
  5. //
  6. #if os(Linux)
  7. import Glibc
  8. #else
  9. import Foundation
  10. #endif
  11. enum HttpParserError: ErrorType {
  12. case ReadBodyFailed(String)
  13. case InvalidStatusLine(String)
  14. case UnknownRequestMethod(String)
  15. }
  16. class HttpParser {
  17. func readHttpRequest(socket: Socket) throws -> HttpRequest {
  18. let statusLine = try socket.readLine()
  19. let statusLineTokens = statusLine.split(" ")
  20. print(statusLineTokens)
  21. if statusLineTokens.count < 3 {
  22. throw HttpParserError.InvalidStatusLine(statusLine)
  23. }
  24. // Make sure the request is of a known type
  25. guard let method = HttpRequest.Method(rawValue: statusLineTokens[0]) else {
  26. throw HttpParserError.UnknownRequestMethod(statusLine)
  27. }
  28. let path = statusLineTokens[1]
  29. let urlParams = extractUrlParams(path)
  30. let headers = try readHeaders(socket)
  31. if let contentLength = headers["content-length"], let contentLengthValue = Int(contentLength) {
  32. let body = try readBody(socket, size: contentLengthValue)
  33. return HttpRequest(url: path, urlParams: urlParams, method: method, headers: headers, body: body, address: nil, params: [:])
  34. }
  35. return HttpRequest(url: path, urlParams: urlParams, method: method, headers: headers, body: nil, address: nil, params: [:])
  36. }
  37. private func extractUrlParams(url: String) -> [(String, String)] {
  38. guard let query = url.split("?").last else {
  39. return []
  40. }
  41. return query.split("&").map { (param: String) -> (String, String) in
  42. let tokens = param.split("=")
  43. guard let name = tokens.first, value = tokens.last else {
  44. return ("", "")
  45. }
  46. return (name.removePercentEncoding(), value.removePercentEncoding())
  47. }
  48. }
  49. private func readBody(socket: Socket, size: Int) throws -> [UInt8] {
  50. var body = [UInt8]()
  51. var counter = 0
  52. while counter < size {
  53. body.append(try socket.read())
  54. counter++
  55. }
  56. return body
  57. }
  58. private func readHeaders(socket: Socket) throws -> [String: String] {
  59. var requestHeaders = [String: String]()
  60. repeat {
  61. let headerLine = try socket.readLine()
  62. if headerLine.isEmpty {
  63. return requestHeaders
  64. }
  65. let headerTokens = headerLine.split(":")
  66. if let name = headerTokens.first where headerTokens.count >= 2 {
  67. let value = headerTokens.dropFirst().joinWithSeparator(":")
  68. requestHeaders[name.lowercaseString] = value.trim()
  69. }
  70. } while true
  71. }
  72. func supportsKeepAlive(headers: [String: String]) -> Bool {
  73. if let value = headers["connection"] {
  74. return "keep-alive" == value.trim()
  75. }
  76. return false
  77. }
  78. }