97 lines
3.2 KiB
Swift
97 lines
3.2 KiB
Swift
import Foundation
|
|
|
|
extension URL {
|
|
public var queryParameters: [String: String]? {
|
|
guard
|
|
let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
|
|
let queryItems = components.queryItems else { return nil }
|
|
return queryItems.reduce(into: [String: String]()) { (result, item) in
|
|
result[item.name] = item.value
|
|
}
|
|
}
|
|
}
|
|
|
|
extension URLRequest {
|
|
func bodySteamAsJSON() -> [String: Any]? {
|
|
guard let bodyStream = self.httpBodyStream else { return nil }
|
|
|
|
bodyStream.open()
|
|
|
|
// Will read 16 chars per iteration. Can use bigger buffer if needed
|
|
let bufferSize: Int = 16
|
|
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
|
|
var dat = Data()
|
|
|
|
while bodyStream.hasBytesAvailable {
|
|
let readDat = bodyStream.read(buffer, maxLength: bufferSize)
|
|
dat.append(buffer, count: readDat)
|
|
}
|
|
|
|
buffer.deallocate()
|
|
bodyStream.close()
|
|
|
|
return try? JSONSerialization.jsonObject(with: dat, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: Any]
|
|
}
|
|
}
|
|
|
|
class MockURLProtocol: URLProtocol {
|
|
|
|
static var baseUrl: String = ""
|
|
static var apiMethodMocks: [ApiMethodMockProtocol] = []
|
|
|
|
override class func canInit(with request: URLRequest) -> Bool {
|
|
return true
|
|
}
|
|
|
|
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
|
|
return request
|
|
}
|
|
|
|
override func startLoading() {
|
|
guard let requestUrl = request.url else { return }
|
|
|
|
let methodMock = MockURLProtocol.apiMethodMocks.first {
|
|
return request.url?.absoluteString == MockURLProtocol.baseUrl + $0.path
|
|
&& request.httpMethod == $0.httpMethod
|
|
}
|
|
|
|
guard let methodMock = methodMock else {
|
|
if let response = HTTPURLResponse(url: requestUrl, statusCode: 404, httpVersion: "HTTP/2", headerFields: [:]) {
|
|
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
|
|
client?.urlProtocolDidFinishLoading(self)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Assuming we use url parameters in GET requests and JSON-encoded body in everything else
|
|
var params: [String: Any] = [:]
|
|
if request.httpBodyStream != nil {
|
|
if let bodyDict = request.bodySteamAsJSON() {
|
|
params = bodyDict
|
|
}
|
|
} else {
|
|
if let urlParams = requestUrl.queryParameters {
|
|
params = urlParams
|
|
}
|
|
}
|
|
|
|
let result = methodMock.response(headers: request.allHTTPHeaderFields ?? [:], params: params)
|
|
guard let response = HTTPURLResponse(url: requestUrl, statusCode: result.status, httpVersion: "HTTP/2", headerFields: [:]) else { return }
|
|
|
|
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
|
|
|
|
if let data = result.data {
|
|
client?.urlProtocol(self, didLoad: data)
|
|
}
|
|
|
|
client?.urlProtocolDidFinishLoading(self)
|
|
|
|
//client?.urlProtocol(self, didFailWithError: error)
|
|
}
|
|
|
|
override func stopLoading() {
|
|
|
|
}
|
|
}
|