HttpParser.swift 2.7 KB

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