Browse Source

Async RequestAdapter (#2628)

* Work towards server trust enhancements.

* Refactor the rewrite! (#2585)

* Refactor request storage out of SessionDelegate.

* Continue development.

* Rename SessionManager -> Session, update environment.

* Rename global Alamofire enum to AF, to avoid collision.

* Sort project.

* Whitespace cleanup.

* Reimplement module changes from bad rebase.

* Finalize errors, refactor testing.

* Standardize self-signed support, add error descriptions.

* Remove per-target setting.

* Make RequestAdapter async.
Jon Shier 7 years ago
parent
commit
7a73af6990
3 changed files with 54 additions and 42 deletions
  1. 5 7
      Source/RequestAdapter.swift
  2. 9 7
      Source/Session.swift
  3. 40 28
      Tests/SessionManagerTests.swift

+ 5 - 7
Source/RequestAdapter.swift

@@ -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)
 }

+ 9 - 7
Source/Session.swift

@@ -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) }

+ 40 - 28
Tests/SessionManagerTests.swift

@@ -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)
         }
     }
 
@@ -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) {
@@ -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) {