Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alamofire 5: Async RequestAdapter #2628

Merged
merged 11 commits into from Nov 22, 2018
12 changes: 5 additions & 7 deletions Source/RequestAdapter.swift
Expand Up @@ -26,12 +26,10 @@ import Foundation

/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary.
public protocol RequestAdapter {
/// Inspects and adapts the specified `URLRequest` in some manner if necessary and returns the result.
/// Inspects and adapts the specified `URLRequest` in some manner and calls the completion handler with the Result.
///
/// - parameter urlRequest: The URL request to adapt.
///
/// - throws: An `Error` if the adaptation encounters an error.
///
/// - returns: The adapted `URLRequest`.
func adapt(_ urlRequest: URLRequest) throws -> URLRequest
/// - Parameters:
/// - urlRequest: The `URLRequest` to adapt.
/// - completion: The completion handler that must be called when adaptation is complete.
func adapt(_ urlRequest: URLRequest, completion: @escaping (_ result: Result<URLRequest>) -> Void)
}
16 changes: 9 additions & 7 deletions Source/Session.swift
Expand Up @@ -347,14 +347,16 @@ open class Session {
guard !request.isCancelled else { return }

if let adapter = adapter {
do {
let adaptedRequest = try adapter.adapt(initialRequest)
rootQueue.async {
request.didAdaptInitialRequest(initialRequest, to: adaptedRequest)
self.didCreateURLRequest(adaptedRequest, for: request)
adapter.adapt(initialRequest) { (result) in
do {
let adaptedRequest = try result.unwrap()
self.rootQueue.async {
request.didAdaptInitialRequest(initialRequest, to: adaptedRequest)
self.didCreateURLRequest(adaptedRequest, for: request)
}
} catch {
self.rootQueue.async { request.didFailToAdaptURLRequest(initialRequest, withError: error) }
}
} catch {
rootQueue.async { request.didFailToAdaptURLRequest(initialRequest, withError: error) }
}
} else {
rootQueue.async { self.didCreateURLRequest(initialRequest, for: request) }
Expand Down
68 changes: 40 additions & 28 deletions Tests/SessionManagerTests.swift
Expand Up @@ -39,13 +39,17 @@ class SessionManagerTestCase: BaseTestCase {
self.throwsError = throwsError
}

func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
guard !throwsError else { throw AFError.invalidURL(url: "") }

var urlRequest = urlRequest
urlRequest.httpMethod = method.rawValue

return urlRequest
func adapt(_ urlRequest: URLRequest, completion: @escaping (Result<URLRequest>) -> Void) {
let result: Result<URLRequest> = Result {
guard !throwsError else { throw AFError.invalidURL(url: "") }

var urlRequest = urlRequest
urlRequest.httpMethod = method.rawValue

return urlRequest
}

completion(result)
}
}

Expand All @@ -57,23 +61,27 @@ class SessionManagerTestCase: BaseTestCase {
var shouldApplyAuthorizationHeader = false
var throwsErrorOnSecondAdapt = false

func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
if throwsErrorOnSecondAdapt && adaptedCount == 1 {
throwsErrorOnSecondAdapt = false
throw AFError.invalidURL(url: "")
}

var urlRequest = urlRequest

adaptedCount += 1

if shouldApplyAuthorizationHeader && adaptedCount > 1 {
if let header = HTTPHeaders.authorization(username: "user", password: "password").first {
urlRequest.setValue(header.value, forHTTPHeaderField: header.key)
func adapt(_ urlRequest: URLRequest, completion: @escaping (Result<URLRequest>) -> Void) {
let result: Result<URLRequest> = Result {
if throwsErrorOnSecondAdapt && adaptedCount == 1 {
throwsErrorOnSecondAdapt = false
throw AFError.invalidURL(url: "")
}

var urlRequest = urlRequest

adaptedCount += 1

if shouldApplyAuthorizationHeader && adaptedCount > 1 {
if let header = HTTPHeaders.authorization(username: "user", password: "password").first {
urlRequest.setValue(header.value, forHTTPHeaderField: header.key)
}
}

return urlRequest
}

return urlRequest
completion(result)
}

func should(_ manager: Session, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
Expand All @@ -93,12 +101,16 @@ class SessionManagerTestCase: BaseTestCase {
var retryCount = 0
var retryErrors: [Error] = []

func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
adaptedCount += 1

if adaptedCount == 1 { throw AFError.invalidURL(url: "") }

return urlRequest
func adapt(_ urlRequest: URLRequest, completion: @escaping (Result<URLRequest>) -> Void) {
let result: Result<URLRequest> = Result {
adaptedCount += 1

if adaptedCount == 1 { throw AFError.invalidURL(url: "") }

return urlRequest
}

completion(result)
}

func should(_ manager: Session, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
Expand Down