Skip to content

Instantly share code, notes, and snippets.

@fikeminkel
Created July 12, 2016 19:23
Show Gist options
  • Save fikeminkel/d0dc22c3189864ad34a359074daa28ac to your computer and use it in GitHub Desktop.
Save fikeminkel/d0dc22c3189864ad34a359074daa28ac to your computer and use it in GitHub Desktop.
struct API {
typealias Result = () throws -> JSON
enum Error: ErrorType {
case ConnectionError(NSError?)
case ServerError(statusCode: Int, message: String?)
case JSONError(NSError?)
}
}
class APIManager: APIManagerAdapter {
static let memoryCacheSize = 2 * 1024 * 1024
static let diskCacheSize = 100 * 1024 * 1024
static let cache = NSURLCache(memoryCapacity: memoryCacheSize, diskCapacity: diskCacheSize, diskPath: nil)
let manager: Alamofire.Manager
init() {
manager = Alamofire.Manager.sharedInstance
NSURLCache.setSharedURLCache(APIManager.cache)
}
func fetchItem(path: String, parameters: [String: AnyObject]? = nil, bypassCache: Bool, handler: API.Result -> Void) -> APIRequest? {
let request = requestFor(path: path, parameters: parameters, bypassCache: bypassCache)
let afRequest = manager.request(request).responseJSON(completionHandler: responseHandlerFor(handler))
return APIRequestImpl(request: afRequest)
}
private func requestHeaders(forPath path: String) -> [String: String] {
var headers = ["X-Timezone": timeZoneProvider.localTimeZoneName]
headers["Authorization"] = {
if let sharedHeader = API.sharedAuthorizationHeader {
return sharedHeader
}
let token = authToken(forPath: path)
return "SNI1-JWT-SHA256 Application=ITK JWT=\(token)"
}()
return headers
}
private func requestFor(path path: String, parameters: [String: AnyObject]? = nil, bypassCache: Bool = false) -> NSMutableURLRequest {
let URL = NSURL(string: urlStringFor(path))!
let cachePolicy: NSURLRequestCachePolicy = {
if bypassCache {
return NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
}
return NSURLRequestCachePolicy.UseProtocolCachePolicy
}()
logManager.logMessage("sending request for: \(URL))")
let URLRequest = NSMutableURLRequest(URL: URL, cachePolicy: cachePolicy, timeoutInterval: 30)
URLRequest.allHTTPHeaderFields = requestHeaders(forPath: path)
let encoding = Alamofire.ParameterEncoding.URL
return encoding.encode(URLRequest, parameters: parameters).0
}
private func responseHandlerFor(resultHandler: API.Result -> Void) -> ResponseHandler {
return {[weak self] response in
guard let strongSelf = self else {
return
}
let requestURLString = response.request?.URL?.absoluteString ?? "??"
guard let serverResponse = response.response else {
strongSelf.logManager.logMessage("Connection Error: \(response.result.error) requesting \(requestURLString)")
resultHandler { throw API.Error.ConnectionError(response.result.error) }
return
}
guard serverResponse.statusCode >= 200 && serverResponse.statusCode < 300 else {
debugPrint("Server Error: \(serverResponse.statusCode) requesting \(response.request?.URL)")
var message: String? = nil
if let value = response.result.value {
message = JSON(value)["display_message"].string
}
resultHandler { throw API.Error.ServerError(statusCode: serverResponse.statusCode, message: message) }
return
}
guard let value = response.result.value else {
strongSelf.logManager.logMessage("JSON Error: \(response.result.error) requesting \(requestURLString)")
resultHandler { throw API.Error.JSONError(response.result.error) }
return
}
resultHandler { return JSON(value) }
}
}
}
class APIRequestImpl: APIRequest {
let request: Alamofire.Request
init(request: Alamofire.Request) {
self.request = request
}
func cancel() {
request.cancel()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment