HttpParser.swift 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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, value = headerTokens.last where headerTokens.count == 2 {
  67. requestHeaders[name.lowercaseString] = value.trim()
  68. }
  69. } while true
  70. }
  71. func supportsKeepAlive(headers: [String: String]) -> Bool {
  72. if let value = headers["connection"] {
  73. return "keep-alive" == value.trim()
  74. }
  75. return false
  76. }
  77. }