URLConvertible.swift 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import Foundation
  2. /// A type which can be converted to an URL string.
  3. public protocol URLConvertible {
  4. var urlValue: URL? { get }
  5. var urlStringValue: String { get }
  6. /// Returns URL query parameters. For convenience, this property will never return `nil` even if
  7. /// there's no query string in the URL. This property doesn't take care of the duplicated keys.
  8. /// For checking duplicated keys, use `queryItems` instead.
  9. ///
  10. /// - seealso: `queryItems`
  11. var queryParameters: [String: String] { get }
  12. /// Returns `queryItems` property of `URLComponents` instance.
  13. ///
  14. /// - seealso: `queryParameters`
  15. @available(iOS 8, *)
  16. var queryItems: [URLQueryItem]? { get }
  17. }
  18. extension URLConvertible {
  19. public var queryParameters: [String: String] {
  20. var parameters = [String: String]()
  21. self.urlValue?.query?.components(separatedBy: "&").forEach { component in
  22. guard let separatorIndex = component.firstIndex(of: "=") else { return }
  23. let keyRange = component.startIndex..<separatorIndex
  24. let valueRange = component.index(after: separatorIndex)..<component.endIndex
  25. let key = String(component[keyRange])
  26. let value = component[valueRange].removingPercentEncoding ?? String(component[valueRange])
  27. parameters[key] = value
  28. }
  29. return parameters
  30. }
  31. @available(iOS 8, *)
  32. public var queryItems: [URLQueryItem]? {
  33. return URLComponents(string: self.urlStringValue)?.queryItems
  34. }
  35. }
  36. extension String: URLConvertible {
  37. public var urlValue: URL? {
  38. if let url = URL(string: self) {
  39. return url
  40. }
  41. var set = CharacterSet()
  42. set.formUnion(.urlHostAllowed)
  43. set.formUnion(.urlPathAllowed)
  44. set.formUnion(.urlQueryAllowed)
  45. set.formUnion(.urlFragmentAllowed)
  46. return self.addingPercentEncoding(withAllowedCharacters: set).flatMap { URL(string: $0) }
  47. }
  48. public var urlStringValue: String {
  49. return self
  50. }
  51. }
  52. extension URL: URLConvertible {
  53. public var urlValue: URL? {
  54. return self
  55. }
  56. public var urlStringValue: String {
  57. return self.absoluteString
  58. }
  59. }