Created
September 6, 2016 10:13
-
-
Save SamClewlow/c00157b710fda79a1da6d6cdb0dc2186 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class MockURLProtocol: NSURLProtocol, NSURLConnectionDelegate { | |
// MARK:- Constants | |
static let harvestMode = false | |
static let mockMode = true | |
// MARK:- Properties | |
var currentRequest: NSURLRequest? | |
var currentTask: NSURLSessionTask? | |
var connection: NSURLConnection? | |
var responseData: NSMutableData? | |
static var callCount: Int = 0 | |
override class func canInitWithRequest(request: NSURLRequest) -> Bool { | |
if !mockMode { return false } | |
if !harvestMode { | |
// Check if request is one we want to handle | |
print("\(#file), \(#function) called \(Int(0)) times, with request: \(request.URL!.absoluteString)") | |
if MockURLProtocol.haveMockJSONForURL(request.URL!) { | |
return true | |
} else { | |
return false | |
} | |
} else { | |
callCount = callCount + 1 | |
print("\(#file), \(#function) called \(Int(callCount)) times, with request: \(request.URL!.absoluteString)") | |
if (NSURLProtocol.propertyForKey("MyURLProtocolHandledKey", inRequest:request) != nil) { | |
return false; | |
} | |
return true; | |
} | |
} | |
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest { | |
return request | |
} | |
override class func requestIsCacheEquivalent(a:NSURLRequest, toRequest: NSURLRequest) -> Bool { | |
return super.requestIsCacheEquivalent(a, toRequest:toRequest) | |
} | |
override func startLoading() { | |
if !MockURLProtocol.harvestMode { | |
// Call got response | |
let response: NSHTTPURLResponse = getResponseForURL(self.request.URL!) | |
self.client!.URLProtocol(self, didReceiveResponse:response, cacheStoragePolicy:.NotAllowed) | |
// Call did load data | |
let responseData: NSData = getResponseDataForURL(self.request.URL!) | |
self.client!.URLProtocol(self, didLoadData:responseData) | |
// Finish the load | |
self.client!.URLProtocolDidFinishLoading(self) | |
} else { | |
// Let the connection pass through and load from NSURL connection | |
var newRequest: NSMutableURLRequest = self.request.mutableCopy() as! NSMutableURLRequest | |
NSURLProtocol.setProperty(true, forKey:"MyURLProtocolHandledKey", inRequest:newRequest) | |
self.connection = NSURLConnection(request: newRequest, delegate:self) | |
} | |
} | |
override func stopLoading() { | |
self.connection!.cancel() | |
self.connection = nil | |
} | |
// MARK: - NSURLConnectionDelegate | |
func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) { | |
if MockURLProtocol.harvestMode { | |
// Dump Response | |
print("Response of URL \(self.request.URL): \(response)") | |
} | |
self.client!.URLProtocol(self, didReceiveResponse:response, cacheStoragePolicy: .NotAllowed) | |
} | |
func connection(connection: NSURLConnection, didReceiveData data: NSData) { | |
// We are only interested in capturing data in harvest mode | |
if MockURLProtocol.harvestMode { | |
if self.responseData == nil { | |
self.responseData = NSMutableData(data: data) | |
} | |
else { | |
self.responseData!.appendData(data) | |
} | |
} | |
self.client!.URLProtocol(self, didLoadData: data) | |
} | |
func connectionDidFinishLoading(connection: NSURLConnection) { | |
if MockURLProtocol.harvestMode { | |
self.dumpJSONData(self.responseData!) | |
} | |
self.client!.URLProtocolDidFinishLoading(self) | |
} | |
func connection(connection: NSURLConnection, didFailWithError error: NSError) { | |
self.client!.URLProtocol(self, didFailWithError: error) | |
} | |
// MARK: - Helpers | |
func getResponseForURL(URL: NSURL) -> NSHTTPURLResponse { | |
guard let fileLocation = URL.URLByDeletingPathExtension?.lastPathComponent else { | |
return getFailureURLResponse() | |
} | |
guard let filePath = NSBundle.mainBundle().pathForResource(fileLocation, ofType: "json") else { | |
return getFailureURLResponse() | |
} | |
guard let data = NSData(contentsOfFile: filePath) else { | |
return getFailureURLResponse() | |
} | |
guard let JSONDict: [String: AnyObject] = try! NSJSONSerialization.JSONObjectWithData(data, options: [.AllowFragments]) as? [String: AnyObject] else { | |
return getFailureURLResponse() | |
} | |
guard let responseDict = JSONDict["response"], | |
let statusCode = (responseDict["statusCode"] as? Int), | |
let headers = responseDict["headers"] as? [String:String] else { | |
return getFailureURLResponse() | |
} | |
// /* | |
// { | |
// "status code": 200, | |
// "headers" : { | |
// "Access-Control-Allow-Methods" : "*", | |
// "Access-Control-Allow-Origin" : "*", | |
// "Connection" : "keep-alive", | |
// "Content-Encoding" : "gzip", | |
// "Content-Length" : 13696, | |
// "Content-Type" : "application/json; charset=utf-8", | |
// "Date" : "Sun, 31 Jan 2016 15:11:13 GMT", | |
// "Server" : "nginx/1.6.0", | |
// "X-Parse-Platform" : "G1", | |
// "X-Runtime" : "0.981976" | |
// } | |
// } | |
// */ | |
if let URLResponse = NSHTTPURLResponse(URL: self.request.URL!, statusCode: statusCode, HTTPVersion: "HTTP/1.1", headerFields: headers) { | |
return URLResponse | |
} else { | |
return getFailureURLResponse() | |
} | |
} | |
func getFailureURLResponse() -> NSHTTPURLResponse { | |
return NSHTTPURLResponse(URL: self.request.URL!, statusCode: 200, HTTPVersion: "HTTP/1.1", headerFields: ["":""])! | |
} | |
func getResponseDataForURL(URL: NSURL) -> NSData { | |
guard let fileLocation = URL.URLByDeletingPathExtension?.lastPathComponent else { | |
return NSData() | |
} | |
guard let filePath = NSBundle.mainBundle().pathForResource(fileLocation, ofType: "json") else { | |
return NSData() | |
} | |
guard let data = NSData(contentsOfFile: filePath) else { | |
return NSData() | |
} | |
guard let JSONDict: [String: AnyObject] = try! NSJSONSerialization.JSONObjectWithData(data, options: [.AllowFragments]) as? [String: AnyObject] else { | |
return NSData() | |
} | |
guard let responseDict = JSONDict["response_data"] else { | |
return NSData() | |
} | |
do { | |
return try NSJSONSerialization.dataWithJSONObject(responseDict, options: [.PrettyPrinted]) | |
} | |
catch let error { | |
print(error) | |
return NSData() | |
} | |
} | |
class func haveMockJSONForURL(URL: NSURL) -> Bool { | |
let fileLocation = URL.URLByDeletingPathExtension!.lastPathComponent | |
let filePath = NSBundle.mainBundle().pathForResource(fileLocation, ofType: "json") | |
if filePath != nil { | |
return true | |
} | |
else { | |
return false | |
} | |
} | |
func dumpJSONData(responseData: NSData) { | |
let JSONString = String(data: responseData, encoding: NSUTF8StringEncoding) | |
print("/n/n/n ****** /n Response for URL: \(self.request.URL!.absoluteString) /n/n \(JSONString), /n/n *******") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment