Skip to content

Instantly share code, notes, and snippets.

@akhtarraza
Last active August 21, 2019 10:37
Show Gist options
  • Save akhtarraza/f2fe63a8921815b2605fa1b1c785b5b6 to your computer and use it in GitHub Desktop.
Save akhtarraza/f2fe63a8921815b2605fa1b1c785b5b6 to your computer and use it in GitHub Desktop.
import Alamofire
public class AuthSessionManager {
static var sharedManager = AuthSessionManager()
public var sessionManager: SessionManager
private init() {
let serverTrustPolicy = ServerTrustPolicy.pinCertificates (
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
)
let manager = ServerTrustPolicyManager(policies: [
"*.google.com" : serverTrustPolicy,
"*.dev.apple.com":.disableEvaluation
])
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
self.sessionManager = SessionManager(configuration: configuration, serverTrustPolicyManager: manager)
}
}
import Alamofire
public class XauthHeadersAdapter: RequestAdapter {
public let authUserId: String?
public let authToken: String?
var additionalHeaders:Parameters?
init(userId: String? = nil, token: String? = nil) {
authUserId = userId
authToken = token
}
public func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
var requestWithAuthHeaders = urlRequest
if let userId = authUserId {
requestWithAuthHeaders.setValue(userId, forHTTPHeaderField: "X-Auth-UID")
}
if let token = authToken {
requestWithAuthHeaders.setValue(token, forHTTPHeaderField: "X-Auth-Token")
}
if let moreHeaders = self.additionalHeaders {
for item in moreHeaders {
requestWithAuthHeaders.setValue(item.value as? String ?? "", forHTTPHeaderField: item.key)
}
}
return requestWithAuthHeaders
}
}
import Alamofire
import SwiftyJSON
import PromiseKit
public typealias APIResponse = (data:JSON?, error:Error?)
public typealias Parameters = [String: Any]
typealias Path = String
typealias Method = Alamofire.HTTPMethod
final class Endpoint {
let method: HTTPMethod
let path: Path
let parameters: Parameters?
let headers: HTTPHeaders?
let encoding: ParameterEncoding
init(method: HTTPMethod = .get,
path:Path,
parameters: Parameters? = nil,
headers: HTTPHeaders? = nil,
encoding: ParameterEncoding = URLEncoding.default) {
self.method = method
self.path = path
self.parameters = parameters
self.headers = headers
self.encoding = encoding
}
}
protocol WebClient {
func request(_ endpoint: Endpoint, completionBlock:@escaping(APIResponse) -> ())
}
public enum WebServiceError: Error {
case invalidResponse(message: String?)
case authError
}
extension WebServiceError: LocalizedError {
public var errorDescription: String? {
switch self {
case.invalidResponse(let message):
return message ?? "Unknown error occured"
case .authError:
return "Your session has timedout, Please re-login to continue."
}
}
}
final class APIClient: WebClient {
private let sessionManger = AuthSessionManager.sharedManager
private let adapter: RequestAdapter?
init(adapter:XauthHeadersAdapter? = nil) {
self.manager.sessionManager.retrier = OAuth2Retrier()
self.adapter = adapter
}
func url(path: Path) -> URL {
return URL(string: path)!
}
func request(_ endpoint: Endpoint, completionBlock:@escaping(APIResponse) -> ()) {
self.manager.sessionManager.adapter = self.adapter
let requestObj = manager.sessionManager.request(self.url(path: endpoint.path), method:endpoint.method, parameters: endpoint.parameters, encoding: endpoint.encoding, headers:endpoint.headers)
.responseJSON(queue: DispatchQueue.init(label: "com.webclient.jsonparser"), options: .mutableLeaves) { response in
switch response.result {
case .success(let val):
print("Response : ",JSON(val))
if JSON(val)["code"] == 401 {
print("Auth error, 401 recieved.")
completionBlock((nil, WebServiceError.authError))
} else {
completionBlock((JSON(val), nil))
}
case .failure(let error):
print(error)
completionBlock((nil, WebServiceError.invalidResponse(message: "Sorry, app had an error. Please try after some time."))
}
}
debugPrint(requestObj)
}
func request(_ endpoint:Endpoint) -> Promise<JSON> {
self.manager.sessionManager.adapter = adapter
return Promise<APIResponse> { seal in
let request = manager.sessionManager.request(self.url(path: endpoint.path), method: endpoint.method, parameters: endpoint.parameters, encoding: endpoint.encoding, headers: endpoint.headers)
request.responseJSON()
.tap {
debugPrint(request)
print($0)
}.done { (json, response) in
//Check for auth error code 401
let jsonData = JSON(json)
if jsonData["code"] == 401 {
seal.reject(WebServiceError.authError)
} else {
seal.fulfill(jsonData)
}
}.catch { error in
debugPrint(request)
debugPrint(error)
seal.reject(WebServiceError.invalidResponse(message: "Sorry, app had an error. Please try after some time."))
}
}
}
}
private class OAuth2Retrier: Alamofire.RequestRetrier {
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
if (error as? AFError)?.responseCode == 401 {
print(error.localizedDescription)
}
completion(false, 0)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment