Procházet zdrojové kódy

Rewrite Advanced Usage for Alamofire 5 (#3057)

* Start AdvancedUsage updates.

* Start rewriting Session section.

* Cleanup.

* WIP.

* Finish Session docs.

* Cleanup.

* Cleanup

* Continue work.

* Progress.

* Further work.

* Add request pipeline docs, refactor security docs.

* Updates.

* Caching and redirect.

* Progress.

* Finish AdvancedUsage.

* Fix typo.

* Fix link.

* Really fix link.

* Cleanup.

* Additional fixes.

* Try to fix test reliability.

* Different test reliability fix.

* Ignore more Ulysses files.

* Another reliability fix.

* Add index, reorder reachability.

* Fix index links.

* Fix more links.

* Fix more links.

* Small edits to advanced usage doc (#3062)

Co-authored-by: Christian Noon <christian.noon@gmail.com>
Jon Shier před 5 roky
rodič
revize
755853f8fb

+ 2 - 0
.gitignore

@@ -37,3 +37,5 @@ playground.xcworkspace
 
 # Carthage
 Carthage/Build
+.UlyssesRoot
+.Ulysses-Settings.plist

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 655 - 699
Documentation/AdvancedUsage.md


+ 4 - 4
Source/RedirectHandler.swift

@@ -35,10 +35,10 @@ public protocol RedirectHandler {
     ///   3. A `nil` value to deny the redirect request and return the body of the redirect response.
     ///
     /// - Parameters:
-    ///   - task:       The task whose request resulted in a redirect.
-    ///   - request:    The URL request object to the new location specified by the redirect response.
-    ///   - response:   The response containing the server's response to the original request.
-    ///   - completion: The closure to execute containing the new request, a modified request, or `nil`.
+    ///   - task:       The `URLSessionTask` whose request resulted in a redirect.
+    ///   - request:    The `URLRequest` to the new location specified by the redirect response.
+    ///   - response:   The `HTTPURLResponse` containing the server's response to the original request.
+    ///   - completion: The closure to execute containing the new `URLRequest`, a modified `URLRequest`, or `nil`.
     func task(_ task: URLSessionTask,
               willBeRedirectedTo request: URLRequest,
               for response: HTTPURLResponse,

+ 3 - 4
Source/Request.swift

@@ -1045,7 +1045,6 @@ public class DownloadRequest: Request {
         /// Specifies that any previous file at the destination `URL` should be removed.
         public static let removePreviousFile = Options(rawValue: 1 << 1)
 
-        /// Returns the raw bitmask value of the option and satisfies the `RawRepresentable` protocol.
         public let rawValue: Int
 
         public init(rawValue: Int) {
@@ -1055,15 +1054,13 @@ public class DownloadRequest: Request {
 
     // MARK: Destination
 
-    /// A closure executed once a download request has successfully completed in order to determine where to move the
+    /// A closure executed once a `DownloadRequest` has successfully completed in order to determine where to move the
     /// temporary file written to during the download process. The closure takes two arguments: the temporary file URL
     /// and the URL response, and returns a two arguments: the file URL where the temporary file should be moved and
     /// the options defining how the file should be moved.
     public typealias Destination = (_ temporaryURL: URL,
                                     _ response: HTTPURLResponse) -> (destinationURL: URL, options: Options)
 
-    // MARK: Destination
-
     /// Creates a download file destination closure which uses the default file manager to move the temporary file to a
     /// file URL in the first available directory with the specified search path directory and search path domain mask.
     ///
@@ -1095,6 +1092,8 @@ public class DownloadRequest: Request {
         return (destination, [])
     }
 
+    // MARK: Downloadable
+
     /// Type describing the source used to create the underlying `URLSessionDownloadTask`.
     public enum Downloadable {
         /// Download should be started from the `URLRequest` produced by the associated `URLRequestConvertible` value.

+ 1 - 1
Source/RequestInterceptor.swift

@@ -45,7 +45,7 @@ public enum RetryResult {
     case retryWithDelay(TimeInterval)
     /// Do not retry.
     case doNotRetry
-    /// Do not retry due to the associated `AFError`.
+    /// Do not retry due to the associated `Error`.
     case doNotRetryWithError(Error)
 }
 

+ 26 - 5
Source/ResponseSerialization.swift

@@ -323,14 +323,14 @@ extension DownloadRequest {
     ///
     /// - Returns:              The request.
     @discardableResult
-    public func response<T: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
-                                                                responseSerializer: T,
-                                                                completionHandler: @escaping (AFDownloadResponse<T.SerializedObject>) -> Void)
+    public func response<Serializer: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
+                                                                         responseSerializer: Serializer,
+                                                                         completionHandler: @escaping (AFDownloadResponse<Serializer.SerializedObject>) -> Void)
         -> Self {
         appendResponseSerializer {
             // Start work that should be on the serialization queue.
             let start = CFAbsoluteTimeGetCurrent()
-            let result: AFResult<T.SerializedObject> = Result {
+            let result: AFResult<Serializer.SerializedObject> = Result {
                 try responseSerializer.serializeDownload(request: self.request,
                                                          response: self.response,
                                                          fileURL: self.fileURL,
@@ -371,7 +371,7 @@ extension DownloadRequest {
                         didComplete = { completionHandler(response) }
 
                     case let .doNotRetryWithError(retryError):
-                        let result: AFResult<T.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
+                        let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
 
                         let response = DownloadResponse(request: self.request,
                                                         response: self.response,
@@ -777,3 +777,24 @@ extension DataRequest {
                         completionHandler: completionHandler)
     }
 }
+
+extension DownloadRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - type:              `Decodable` type to decode from response data.
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - decoder:           `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
+    ///   - completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
+                                                queue: DispatchQueue = .main,
+                                                decoder: DataDecoder = JSONDecoder(),
+                                                completionHandler: @escaping (AFDownloadResponse<T>) -> Void) -> Self {
+        return response(queue: queue,
+                        responseSerializer: DecodableResponseSerializer(decoder: decoder),
+                        completionHandler: completionHandler)
+    }
+}

+ 1 - 1
Tests/AFError+AlamofireTests.swift

@@ -174,7 +174,7 @@ extension AFError {
         if case let .urlRequestValidationFailed(reason) = self, reason.isBodyDataInGETRequest { return true }
         return false
     }
-    
+
     var isHostURLError: Bool {
         guard let errorCode = (underlyingError as? URLError)?.code else { return false }
         return [.cannotConnectToHost, .cannotFindHost].contains(errorCode)

+ 7 - 5
Tests/DownloadTests.swift

@@ -366,6 +366,8 @@ class DownloadResponseTestCase: BaseTestCase {
     }
 }
 
+// MARK: -
+
 final class DownloadRequestEventsTestCase: BaseTestCase {
     func testThatDownloadRequestTriggersAllAppropriateLifetimeEvents() {
         // Given
@@ -453,7 +455,7 @@ final class DownloadRequestEventsTestCase: BaseTestCase {
         eventMonitor.requestDidCancelTask = { _, _ in didCancelTask.fulfill() }
 
         // When
-        let request = session.download(URLRequest.makeHTTPBinRequest()).response { _ in
+        let request = session.download(URLRequest.makeHTTPBinRequest(path: "delay/5")).response { _ in
             responseHandler.fulfill()
         }
 
@@ -684,7 +686,7 @@ final class DownloadResumeDataTestCase: BaseTestCase {
 
 // MARK: -
 
-class DownloadResponseMapTestCase: BaseTestCase {
+final class DownloadResponseMapTestCase: BaseTestCase {
     func testThatMapTransformsSuccessValue() {
         // Given
         let urlString = "https://httpbin.org/get"
@@ -742,7 +744,7 @@ class DownloadResponseMapTestCase: BaseTestCase {
 
 // MARK: -
 
-class DownloadResponseTryMapTestCase: BaseTestCase {
+final class DownloadResponseTryMapTestCase: BaseTestCase {
     func testThatTryMapTransformsSuccessValue() {
         // Given
         let urlString = "https://httpbin.org/get"
@@ -832,7 +834,7 @@ class DownloadResponseTryMapTestCase: BaseTestCase {
     }
 }
 
-class DownloadResponseMapErrorTestCase: BaseTestCase {
+final class DownloadResponseMapErrorTestCase: BaseTestCase {
     func testThatMapErrorTransformsFailureValue() {
         // Given
         let urlString = "https://invalid-url-here.org/this/does/not/exist"
@@ -891,7 +893,7 @@ class DownloadResponseMapErrorTestCase: BaseTestCase {
 
 // MARK: -
 
-class DownloadResponseTryMapErrorTestCase: BaseTestCase {
+final class DownloadResponseTryMapErrorTestCase: BaseTestCase {
     func testThatTryMapErrorPreservesSuccessValue() {
         // Given
         let urlString = "https://httpbin.org/get"

+ 4 - 2
Tests/HTTPBin.swift

@@ -51,7 +51,9 @@ extension URLRequest {
         return request
     }
 
-    static func make(url: URL = URL(string: "https://httpbin.org/get")!, method: HTTPMethod = .get, headers: HTTPHeaders = .init()) -> URLRequest {
+    static func make(url: URL = URL(string: "https://httpbin.org/get")!,
+                     method: HTTPMethod = .get,
+                     headers: HTTPHeaders = .init()) -> URLRequest {
         var request = URLRequest(url: url)
         request.method = method
         request.headers = headers
@@ -62,7 +64,7 @@ extension URLRequest {
 
 extension Data {
     var asString: String {
-        return String(data: self, encoding: .utf8)!
+        return String(decoding: self, as: UTF8.self)
     }
 }
 

+ 1 - 1
Tests/UploadTests.swift

@@ -715,7 +715,7 @@ final class UploadRequestEventsTestCase: BaseTestCase {
 
         // When
         let request = session.upload(Data("PAYLOAD".utf8),
-                                     with: URLRequest.makeHTTPBinRequest(path: "post", method: .post)).response { _ in
+                                     with: URLRequest.makeHTTPBinRequest(path: "delay/5", method: .post)).response { _ in
             responseHandler.fulfill()
         }
 

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů