HttpRouter.swift 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //
  2. // HttpRouter.swift
  3. // Swifter
  4. // Copyright (c) 2015 Damian Kołakowski. All rights reserved.
  5. //
  6. import Foundation
  7. public class HttpRouter {
  8. private class Node {
  9. var nodes = [String: Node]()
  10. var handler: (HttpRequest -> HttpResponse)? = nil
  11. }
  12. private var rootNode = Node()
  13. public func routes() -> [String] {
  14. var routes = [String]()
  15. for (_, child) in rootNode.nodes {
  16. routes.appendContentsOf(routesForNode(child));
  17. }
  18. return routes
  19. }
  20. private func routesForNode(node: Node, prefix: String = "") -> [String] {
  21. var result = [String]()
  22. if node.handler != nil {
  23. result.append(prefix)
  24. }
  25. for (key, child) in node.nodes {
  26. result.appendContentsOf(routesForNode(child, prefix: prefix + "/" + key));
  27. }
  28. return result
  29. }
  30. public func register(method: String?, path: String, handler: (HttpRequest -> HttpResponse)?) {
  31. var pathSegments = stripQuery(path).split("/")
  32. if let method = method {
  33. pathSegments.insert(method, atIndex: 0)
  34. } else {
  35. pathSegments.insert("*", atIndex: 0)
  36. }
  37. var pathSegmentsGenerator = pathSegments.generate()
  38. inflate(&rootNode, generator: &pathSegmentsGenerator).handler = handler
  39. }
  40. public func route(method: String?, path: String) -> ([String: String], HttpRequest -> HttpResponse)? {
  41. if let method = method {
  42. let pathSegments = (method + "/" + stripQuery(path)).split("/")
  43. var pathSegmentsGenerator = pathSegments.generate()
  44. var params = [String:String]()
  45. if let handler = findHandler(&rootNode, params: &params, generator: &pathSegmentsGenerator) {
  46. return (params, handler)
  47. }
  48. }
  49. let pathSegments = ("*/" + stripQuery(path)).split("/")
  50. var pathSegmentsGenerator = pathSegments.generate()
  51. var params = [String:String]()
  52. if let handler = findHandler(&rootNode, params: &params, generator: &pathSegmentsGenerator) {
  53. return (params, handler)
  54. }
  55. return nil
  56. }
  57. private func inflate(inout node: Node, inout generator: IndexingGenerator<[String]>) -> Node {
  58. if let pathSegment = generator.next() {
  59. if let _ = node.nodes[pathSegment] {
  60. return inflate(&node.nodes[pathSegment]!, generator: &generator)
  61. }
  62. var nextNode = Node()
  63. node.nodes[pathSegment] = nextNode
  64. return inflate(&nextNode, generator: &generator)
  65. }
  66. return node
  67. }
  68. private func findHandler(inout node: Node, inout params: [String: String], inout generator: IndexingGenerator<[String]>) -> (HttpRequest -> HttpResponse)? {
  69. guard let pathToken = generator.next() else {
  70. return node.handler
  71. }
  72. let variableNodes = node.nodes.filter { $0.0.characters.first == ":" }
  73. if let variableNode = variableNodes.first {
  74. params[variableNode.0] = pathToken
  75. return findHandler(&node.nodes[variableNode.0]!, params: &params, generator: &generator)
  76. }
  77. if let _ = node.nodes[pathToken] {
  78. return findHandler(&node.nodes[pathToken]!, params: &params, generator: &generator)
  79. }
  80. if let _ = node.nodes["*"] {
  81. return findHandler(&node.nodes["*"]!, params: &params, generator: &generator)
  82. }
  83. return nil
  84. }
  85. private func stripQuery(path: String) -> String {
  86. if let path = path.split("?").first {
  87. return path
  88. }
  89. return path
  90. }
  91. }