HttpParser.swift 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. }
  15. class HttpParser {
  16. func readHttpRequest(socket: Socket) throws -> HttpRequest {
  17. let statusLine = try socket.readLine()
  18. let statusLineTokens = statusLine.split(" ")
  19. print(statusLineTokens)
  20. if statusLineTokens.count < 3 {
  21. throw HttpParserError.InvalidStatusLine(statusLine)
  22. }
  23. let method = statusLineTokens[0]
  24. let path = statusLineTokens[1]
  25. let urlParams = extractUrlParams(path)
  26. let headers = try readHeaders(socket)
  27. if let contentLength = headers["content-length"], let contentLengthValue = Int(contentLength) {
  28. let body = try readBody(socket, size: contentLengthValue)
  29. return HttpRequest(url: path, urlParams: urlParams, method: method, headers: headers, body: body, address: nil, params: [:])
  30. }
  31. return HttpRequest(url: path, urlParams: urlParams, method: method, headers: headers, body: nil, address: nil, params: [:])
  32. }
  33. private func extractUrlParams(url: String) -> [(String, String)] {
  34. guard let query = url.split("?").last else {
  35. return []
  36. }
  37. return query.split("&").map { (param: String) -> (String, String) in
  38. let tokens = param.split("=")
  39. guard let name = tokens.first, value = tokens.last else {
  40. return ("", "")
  41. }
  42. return (name.removePercentEncoding(), value.removePercentEncoding())
  43. }
  44. }
  45. private func readBody(socket: Socket, size: Int) throws -> [UInt8] {
  46. var body = [UInt8]()
  47. var counter = 0
  48. while counter < size {
  49. body.append(try socket.read())
  50. counter++
  51. }
  52. return body
  53. }
  54. private func readHeaders(socket: Socket) throws -> [String: String] {
  55. var requestHeaders = [String: String]()
  56. repeat {
  57. let headerLine = try socket.readLine()
  58. if headerLine.isEmpty {
  59. return requestHeaders
  60. }
  61. let headerTokens = headerLine.split(":")
  62. if let name = headerTokens.first, value = headerTokens.last where headerTokens.count == 2 {
  63. requestHeaders[name.lowercaseString] = value.trim()
  64. }
  65. } while true
  66. }
  67. func supportsKeepAlive(headers: [String: String]) -> Bool {
  68. if let value = headers["connection"] {
  69. return "keep-alive" == value.trim()
  70. }
  71. return false
  72. }
  73. }