// // NetworkHelper.swift // acrypto // // Created by HaKr on 21/10/17. // Copyright © 2017 DWorkS. All rights reserved. // import Foundation import Alamofire public protocol NetworkCompletionDelegate { func onResponse(_ response: Any) func onErrorResponse(_ error: Error) } class NetworkHelper: NSObject { static var sessionManager: SessionManager! static var sessionConfiguration: URLSessionConfiguration! static var sessionManagerMaster: SessionManager! static var sessionConfigurationMaster: URLSessionConfiguration! static func getSessionManger() -> SessionManager { if(nil == sessionManager) { let capacity = 50 * 1024 * 1024 // MBs let urlCache = SmartUrlCache(memoryCapacity: capacity, diskCapacity: capacity, diskPath: nil) sessionConfiguration = URLSessionConfiguration.default sessionConfiguration.requestCachePolicy = .returnCacheDataElseLoad sessionConfiguration.urlCache = urlCache sessionConfiguration.timeoutIntervalForRequest = 10 sessionManager = Alamofire.SessionManager(configuration: sessionConfiguration) } return sessionManager } static func getSessionMangerMaster() -> SessionManager { if(nil == sessionManagerMaster) { let capacity = 50 * 1024 * 1024 // MBs let urlCache = SmartUrlMasterCache(memoryCapacity: capacity, diskCapacity: capacity, diskPath: nil) sessionConfigurationMaster = URLSessionConfiguration.default sessionConfigurationMaster.requestCachePolicy = .returnCacheDataElseLoad sessionConfigurationMaster.urlCache = urlCache sessionManagerMaster = Alamofire.SessionManager(configuration: sessionConfigurationMaster) } return sessionManagerMaster } static func removeCachedUrl(url: String, parameters: Parameters? = nil) { let headers: HTTPHeaders? = nil var originalRequest: URLRequest do { originalRequest = try URLRequest(url: url, method: .get, headers: headers) let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters) sessionConfiguration.urlCache?.removeCachedResponse(for: encodedURLRequest) addCache(url: url, data: Data(), parameters: parameters) } catch { Log.info(error) } } static func removeMasterCachedUrl(url: String, parameters: Parameters? = nil) { let headers: HTTPHeaders? = nil var originalRequest: URLRequest do { originalRequest = try URLRequest(url: url, method: .get, headers: headers) let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters) sessionConfiguration.urlCache?.removeCachedResponse(for: encodedURLRequest) addMasterCache(url: url, data: Data(), parameters: parameters) } catch { Log.info(error) } } static func removeAllCached() { sessionConfigurationMaster.urlCache?.removeAllCachedResponses() } static func addCache(url: String, data: Data, parameters: Parameters? = nil) { let headers: HTTPHeaders? = nil do { let originalRequest = try URLRequest(url: url, method: .get, headers: headers) let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters) let newResponse = HTTPURLResponse(url: URL(string: url)!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Cache-Control":"private, max-age=0, s-maxage=0"]) let cachedResponse = CachedURLResponse(response: newResponse!, data: data) sessionConfiguration.urlCache?.storeCachedResponse(cachedResponse, for: encodedURLRequest) } catch { Log.info(error) } } static func addMasterCache(url: String, data: Data, parameters: Parameters? = nil) { let headers: HTTPHeaders? = nil do { let originalRequest = try URLRequest(url: url, method: .get, headers: headers) let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters) let newResponse = HTTPURLResponse(url: URL(string: url)!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Cache-Control":"private, max-age=0, s-maxage=0"]) let cachedResponse = CachedURLResponse(response: newResponse!, data: data) sessionConfigurationMaster.urlCache?.storeCachedResponse(cachedResponse, for: encodedURLRequest) } catch { Log.info(error) } } static func requestJSON(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){ getSessionManger().request(url, method: .get, parameters: parameters) .validate() .responseJSON { response in switch response.result { case .success: Log.info("Request: \(String(describing: response.request))") completionDelegate.onResponse(response) break case .failure(let error): Log.info("Error: \(error)") completionDelegate.onErrorResponse(error) } } } static func requestJSON(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse) -> Void) { getSessionManger().request(url, method: .get, parameters: parameters).validate().responseJSON(completionHandler: completionHandler) } static func requestString(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){ getSessionManger().request(url, method: .get, parameters: parameters) .validate() .responseString { response in switch response.result { case .success: Log.info("Request: \(String(describing: response.request))") completionDelegate.onResponse(response) break case .failure(let error): Log.info("Error: \(error)") completionDelegate.onErrorResponse(error) } } } static func requestString(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse) -> Void) { getSessionManger().request(url, method: .get, parameters: parameters).validate().responseString(completionHandler: completionHandler) } static func requestJSONMaster(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){ getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders()) .validate() .responseJSON { response in switch response.result { case .success: Log.info("Request: \(String(describing: response.request))") completionDelegate.onResponse(response) break case .failure(let error): Log.info("Error: \(error)") completionDelegate.onErrorResponse(error) } } } static func requestJSONMaster(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse) -> Void) { getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders()).validate().responseJSON(completionHandler: completionHandler) } static func requestStringMaster(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){ getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders()) .validate() .responseString { response in switch response.result { case .success: Log.info("Request: \(String(describing: response.request))") completionDelegate.onResponse(response) break case .failure(let error): Log.info("Error: \(error)") completionDelegate.onErrorResponse(error) } } } static func requestStringMaster(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse) -> Void) { getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders()).validate().responseString(completionHandler: completionHandler) } static func getHeaders() -> HTTPHeaders{ var headers: HTTPHeaders = [:] headers.updateValue(Constants.AUTH, forKey: Constants.AUTH_HEADER) headers.updateValue(AppHelper.versionName ?? "", forKey: Constants.CLIENT_HEADER) return headers } } class SmartUrlCache: URLCache { let CACHE_EXPIRY = "cache_expiry"; let cacheExpireInterval: TimeInterval = 60*60; override func cachedResponse(for request: URLRequest) -> CachedURLResponse? { var response: CachedURLResponse? = nil if let cachedResponse = super.cachedResponse(for: request) { if let userInfo = cachedResponse.userInfo { if let cacheDate = userInfo[CACHE_EXPIRY] as! NSDate? { // check if the cache data are expired let count = cachedResponse.data.count if (cacheDate.timeIntervalSinceNow < -cacheExpireInterval) || count == 0 { self.removeCachedResponse(for: request) } else { response = cachedResponse } } } } return response; } override func removeCachedResponse(for request: URLRequest) { super.removeCachedResponse(for: request) } override func storeCachedResponse(_ cachedResponse: CachedURLResponse, for request: URLRequest) { var userInfo = NSMutableDictionary() if let cachedUserInfo = cachedResponse.userInfo { userInfo = NSMutableDictionary(dictionary: cachedUserInfo) } if let cacheDate = userInfo[CACHE_EXPIRY] as! NSDate? { // check if the cache data are expired if (cacheDate.timeIntervalSinceNow < -cacheExpireInterval) { userInfo[CACHE_EXPIRY] = NSDate() } } else { userInfo[CACHE_EXPIRY] = NSDate() } let newCachedResponse = CachedURLResponse(response: cachedResponse.response, data: cachedResponse.data, userInfo: userInfo as [NSObject : AnyObject], storagePolicy: cachedResponse.storagePolicy) super.storeCachedResponse(newCachedResponse, for: request) } } class SmartUrlMasterCache: URLCache { override func cachedResponse(for request: URLRequest) -> CachedURLResponse? { var response: CachedURLResponse? = nil if let cachedResponse = super.cachedResponse(for: request) { let count = cachedResponse.data.count if count == 0 { self.removeCachedResponse(for: request) } else { response = cachedResponse } } return response; } override func removeCachedResponse(for request: URLRequest) { super.removeCachedResponse(for: request) } }