88 lines
3.2 KiB
Swift
88 lines
3.2 KiB
Swift
|
import Foundation
|
||
|
|
||
|
extension URLComponents {
|
||
|
static func with(host: String, scheme: String = "https", path: String = "/", queryParameters: [String: Any]? = nil) -> URLComponents {
|
||
|
var components = URLComponents()
|
||
|
components.host = host
|
||
|
components.scheme = scheme
|
||
|
components.path = path
|
||
|
components.replacePercentEncodedQueryWithQueryParameters(queryParameters)
|
||
|
return components
|
||
|
}
|
||
|
|
||
|
public static func percentEncodedQueryStringFrom(_ queryParameters: [String: Any]) -> String {
|
||
|
var query = ""
|
||
|
|
||
|
// sort query parameters by key, this allows for consistency when itemKeys are generated for the persistent cache.
|
||
|
struct KeyValue {
|
||
|
let key: String
|
||
|
let value: Any
|
||
|
}
|
||
|
|
||
|
var unorderedKeyValues: [KeyValue] = []
|
||
|
|
||
|
for (name, value) in queryParameters {
|
||
|
|
||
|
unorderedKeyValues.append(KeyValue(key: name, value: value))
|
||
|
}
|
||
|
|
||
|
let orderedKeyValues = unorderedKeyValues.sorted { (lhs, rhs) -> Bool in
|
||
|
return lhs.key < rhs.key
|
||
|
}
|
||
|
|
||
|
for keyValue in orderedKeyValues {
|
||
|
guard
|
||
|
let encodedName = keyValue.key.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryComponentAllowed),
|
||
|
let encodedValue = String(describing: keyValue.value).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryComponentAllowed) else {
|
||
|
continue
|
||
|
}
|
||
|
if query != "" {
|
||
|
query.append("&")
|
||
|
}
|
||
|
|
||
|
query.append("\(encodedName)=\(encodedValue)")
|
||
|
}
|
||
|
|
||
|
return query
|
||
|
}
|
||
|
|
||
|
mutating func appendQueryParametersToPercentEncodedQuery(_ queryParameters: [String: Any]?) {
|
||
|
guard let queryParameters = queryParameters else {
|
||
|
return
|
||
|
}
|
||
|
var newPEQ = ""
|
||
|
if let existing = percentEncodedQuery {
|
||
|
newPEQ = existing + "&"
|
||
|
}
|
||
|
newPEQ = newPEQ + URLComponents.percentEncodedQueryStringFrom(queryParameters)
|
||
|
percentEncodedQuery = newPEQ
|
||
|
}
|
||
|
|
||
|
mutating func replacePercentEncodedQueryWithQueryParameters(_ queryParameters: [String: Any]?) {
|
||
|
guard let queryParameters = queryParameters else {
|
||
|
percentEncodedQuery = nil
|
||
|
return
|
||
|
}
|
||
|
percentEncodedQuery = URLComponents.percentEncodedQueryStringFrom(queryParameters)
|
||
|
}
|
||
|
|
||
|
mutating func replacePercentEncodedPathWithPathComponents(_ pathComponents: [String]?) {
|
||
|
guard let pathComponents = pathComponents else {
|
||
|
percentEncodedPath = "/"
|
||
|
return
|
||
|
}
|
||
|
let fullComponents = [""] + pathComponents
|
||
|
#if DEBUG
|
||
|
for component in fullComponents {
|
||
|
assert(!component.contains("/"))
|
||
|
}
|
||
|
#endif
|
||
|
percentEncodedPath = fullComponents.joined(separator: "/") // NSString.path(with: components) removes the trailing slash that the reading list API needs
|
||
|
}
|
||
|
|
||
|
public func wmf_URLWithLanguageVariantCode(_ code: String?) -> URL? {
|
||
|
return (self as NSURLComponents).wmf_URL(withLanguageVariantCode: code)
|
||
|
}
|
||
|
|
||
|
}
|