HttpRouter.swift 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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 var handlers: [(String?, pattern: [String], HttpRequest -> HttpResponse)] = []
  9. public func routes() -> [(method: String?, path: String)] {
  10. return handlers.map { ($0.0, "/" + $0.pattern.joinWithSeparator("/")) }
  11. }
  12. public func register(method: String?, path: String, handler: HttpRequest -> HttpResponse) {
  13. handlers.append((method, path.split("/"), handler))
  14. handlers.sortInPlace { $0.0.pattern.count < $0.1.pattern.count }
  15. }
  16. public func unregister(method: String?, path: String) {
  17. let tokens = path.split("/")
  18. handlers = handlers.filter { (meth, pattern, _) -> Bool in
  19. return meth != method || pattern != tokens
  20. }
  21. }
  22. public func select(method: String?, url: String) -> ([String: String], HttpRequest -> HttpResponse)? {
  23. let urlTokens = url.split("/")
  24. for (meth, pattern, handler) in handlers {
  25. if meth == nil || meth! == method {
  26. if let params = matchParams(pattern, valueTokens: urlTokens) {
  27. return (params, handler)
  28. }
  29. }
  30. }
  31. return nil
  32. }
  33. public func matchParams(patternTokens: [String], valueTokens: [String]) -> [String: String]? {
  34. var params = [String: String]()
  35. for index in 0..<valueTokens.count {
  36. if index >= patternTokens.count {
  37. return nil
  38. }
  39. let patternToken = patternTokens[index]
  40. let valueToken = valueTokens[index]
  41. if patternToken.isEmpty {
  42. if patternToken != valueToken {
  43. return nil
  44. }
  45. }
  46. if patternToken.characters.first == ":" {
  47. #if os(Linux)
  48. params[patternToken.substringFromIndex(1)] = valueToken
  49. #else
  50. params[patternToken.substringFromIndex(patternToken.characters.startIndex.successor())] = valueToken
  51. #endif
  52. } else {
  53. if patternToken != valueToken {
  54. return nil
  55. }
  56. }
  57. }
  58. return params
  59. }
  60. }