Commit 4045a382d42cd91676ddb2d369de041d7004c0e5

Authored by yanglingyu
0 parents

元码工程初始化提交

Too many changes to show.

To preserve performance only 15 of 109 files are displayed.

Podfile 0 → 100644
  1 +++ a/Podfile
  1 +# Uncomment the next line to define a global platform for your project
  2 +# platform :ios, '9.0'
  3 +
  4 +target 'metaCode' do
  5 + # Comment the next line if you don't want to use dynamic frameworks
  6 + use_frameworks!
  7 +
  8 + pod 'Alamofire'
  9 +
  10 + # Pods for metaCode
  11 +
  12 + target 'metaCodeTests' do
  13 + inherit! :search_paths
  14 + # Pods for testing
  15 + end
  16 +
  17 + target 'metaCodeUITests' do
  18 + # Pods for testing
  19 + end
  20 +
  21 +end
Podfile.lock 0 → 100644
  1 +++ a/Podfile.lock
  1 +PODS:
  2 + - Alamofire (5.7.1)
  3 +
  4 +DEPENDENCIES:
  5 + - Alamofire
  6 +
  7 +SPEC REPOS:
  8 + trunk:
  9 + - Alamofire
  10 +
  11 +SPEC CHECKSUMS:
  12 + Alamofire: 0123a34370cb170936ae79a8df46cc62b2edeb88
  13 +
  14 +PODFILE CHECKSUM: eff4d6eae7591679717a1823b39a746e49739fe5
  15 +
  16 +COCOAPODS: 1.11.3
Pods/Alamofire/LICENSE 0 → 100644
  1 +++ a/Pods/Alamofire/LICENSE
  1 +Copyright (c) 2014-2022 Alamofire Software Foundation (http://alamofire.org/)
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to deal
  5 +in the Software without restriction, including without limitation the rights
  6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7 +copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in
  11 +all copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19 +THE SOFTWARE.
Pods/Alamofire/README.md 0 → 100644
  1 +++ a/Pods/Alamofire/README.md
  1 +![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/master/Resources/AlamofireLogo.png)
  2 +
  3 +[![Swift](https://img.shields.io/badge/Swift-5.5_5.6_5.7_5.8-orange?style=flat-square)](https://img.shields.io/badge/Swift-5.5_5.6_5.7_5.8-Orange?style=flat-square)
  4 +[![Platforms](https://img.shields.io/badge/Platforms-macOS_iOS_tvOS_watchOS_Linux_Windows-yellowgreen?style=flat-square)](https://img.shields.io/badge/Platforms-macOS_iOS_tvOS_watchOS_Linux_Windows-Green?style=flat-square)
  5 +[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Alamofire.svg?style=flat-square)](https://img.shields.io/cocoapods/v/Alamofire.svg)
  6 +[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square)](https://github.com/Carthage/Carthage)
  7 +[![Swift Package Manager](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)
  8 +[![Twitter](https://img.shields.io/badge/twitter-@AlamofireSF-blue.svg?style=flat-square)](https://twitter.com/AlamofireSF)
  9 +[![Swift Forums](https://img.shields.io/badge/Swift_Forums-Alamofire-orange?style=flat-square)](https://forums.swift.org/c/related-projects/alamofire/37)
  10 +
  11 +Alamofire is an HTTP networking library written in Swift.
  12 +
  13 +- [Features](#features)
  14 +- [Component Libraries](#component-libraries)
  15 +- [Requirements](#requirements)
  16 +- [Migration Guides](#migration-guides)
  17 +- [Communication](#communication)
  18 +- [Installation](#installation)
  19 +- [Contributing](#contributing)
  20 +- [Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#using-alamofire)
  21 + - [**Introduction -**](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#introduction) [Making Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#making-requests), [Response Handling](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-handling), [Response Validation](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-validation), [Response Caching](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-caching)
  22 + - **HTTP -** [HTTP Methods](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-methods), [Parameters and Parameter Encoder](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md##request-parameters-and-parameter-encoders), [HTTP Headers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-headers), [Authentication](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#authentication)
  23 + - **Large Data -** [Downloading Data to a File](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#downloading-data-to-a-file), [Uploading Data to a Server](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server)
  24 + - **Tools -** [Statistical Metrics](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#statistical-metrics), [cURL Command Output](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#curl-command-output)
  25 +- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md)
  26 + - **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#sessiondelegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request)
  27 + - **Routing -** [Routing Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#routing-requests), [Adapting and Retrying Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#adapting-and-retrying-requests-with-requestinterceptor)
  28 + - **Model Objects -** [Custom Response Handlers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#customizing-response-handlers)
  29 + - **Advanced Concurrency -** [Swift Concurrency](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#using-alamofire-with-swift-concurrency) and [Combine](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#using-alamofire-with-combine)
  30 + - **Connection -** [Security](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security), [Network Reachability](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability)
  31 +- [Open Radars](#open-radars)
  32 +- [FAQ](#faq)
  33 +- [Credits](#credits)
  34 +- [Donations](#donations)
  35 +- [License](#license)
  36 +
  37 +## Features
  38 +
  39 +- [x] Chainable Request / Response Methods
  40 +- [x] Swift Concurrency Support Back to iOS 13, macOS 10.15, tvOS 13, and watchOS 6.
  41 +- [x] Combine Support
  42 +- [x] URL / JSON Parameter Encoding
  43 +- [x] Upload File / Data / Stream / MultipartFormData
  44 +- [x] Download File using Request or Resume Data
  45 +- [x] Authentication with `URLCredential`
  46 +- [x] HTTP Response Validation
  47 +- [x] Upload and Download Progress Closures with Progress
  48 +- [x] cURL Command Output
  49 +- [x] Dynamically Adapt and Retry Requests
  50 +- [x] TLS Certificate and Public Key Pinning
  51 +- [x] Network Reachability
  52 +- [x] Comprehensive Unit and Integration Test Coverage
  53 +- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
  54 +
  55 +## Component Libraries
  56 +
  57 +In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem.
  58 +
  59 +- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) - An image library including image response serializers, `UIImage` and `UIImageView` extensions, custom image filters, an auto-purging in-memory cache, and a priority-based image downloading system.
  60 +- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) - Controls the visibility of the network activity indicator on iOS using Alamofire. It contains configurable delay timers to help mitigate flicker and can support `URLSession` instances not managed by Alamofire.
  61 +
  62 +## Requirements
  63 +
  64 +| Platform | Minimum Swift Version | Installation | Status |
  65 +| --- | --- | --- | --- |
  66 +| iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+ | 5.5 | [CocoaPods](#cocoapods), [Carthage](#carthage), [Swift Package Manager](#swift-package-manager), [Manual](#manually) | Fully Tested |
  67 +| Linux | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
  68 +| Windows | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
  69 +
  70 +#### Known Issues on Linux and Windows
  71 +
  72 +Alamofire builds on Linux and Windows but there are missing features and many issues in the underlying `swift-corelibs-foundation` that prevent full functionality and may cause crashes. These include:
  73 +- `ServerTrustManager` and associated certificate functionality is unavailable, so there is no certificate pinning and no client certificate support.
  74 +- Various methods of HTTP authentication may crash, including HTTP Basic and HTTP Digest. Crashes may occur if responses contain server challenges.
  75 +- Cache control through `CachedResponseHandler` and associated APIs is unavailable, as the underlying delegate methods aren't called.
  76 +- `URLSessionTaskMetrics` are never gathered.
  77 +
  78 +Due to these issues, Alamofire is unsupported on Linux and Windows. Please report any crashes to the [Swift bug reporter](https://bugs.swift.org).
  79 +
  80 +## Migration Guides
  81 +
  82 +- [Alamofire 5.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%205.0%20Migration%20Guide.md)
  83 +- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md)
  84 +- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md)
  85 +- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
  86 +
  87 +## Communication
  88 +- If you **need help with making network requests** using Alamofire, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`.
  89 +- If you need to **find or understand an API**, check [our documentation](http://alamofire.github.io/Alamofire/) or [Apple's documentation for `URLSession`](https://developer.apple.com/documentation/foundation/url_loading_system), on top of which Alamofire is built.
  90 +- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
  91 +- If you'd like to **discuss Alamofire best practices**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
  92 +- If you'd like to **discuss a feature request**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
  93 +- If you **found a bug**, open an issue here on GitHub and follow the guide. The more detail the better!
  94 +
  95 +## Installation
  96 +
  97 +### CocoaPods
  98 +
  99 +[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`:
  100 +
  101 +```ruby
  102 +pod 'Alamofire'
  103 +```
  104 +
  105 +### Carthage
  106 +
  107 +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`:
  108 +
  109 +```ogdl
  110 +github "Alamofire/Alamofire"
  111 +```
  112 +
  113 +### Swift Package Manager
  114 +
  115 +The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler.
  116 +
  117 +Once you have your Swift package set up, adding Alamofire as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`.
  118 +
  119 +```swift
  120 +dependencies: [
  121 + .package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.6.4"))
  122 +]
  123 +```
  124 +
  125 +### Manually
  126 +
  127 +If you prefer not to use any of the aforementioned dependency managers, you can integrate Alamofire into your project manually.
  128 +
  129 +#### Embedded Framework
  130 +
  131 +- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository:
  132 +
  133 + ```bash
  134 + $ git init
  135 + ```
  136 +
  137 +- Add Alamofire as a git [submodule](https://git-scm.com/docs/git-submodule) by running the following command:
  138 +
  139 + ```bash
  140 + $ git submodule add https://github.com/Alamofire/Alamofire.git
  141 + ```
  142 +
  143 +- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project.
  144 +
  145 + > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.
  146 +
  147 +- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.
  148 +- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.
  149 +- In the tab bar at the top of that window, open the "General" panel.
  150 +- Click on the `+` button under the "Embedded Binaries" section.
  151 +- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder.
  152 +
  153 + > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`.
  154 +
  155 +- Select the top `Alamofire.framework` for iOS and the bottom one for macOS.
  156 +
  157 + > You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS`, or `Alamofire watchOS`.
  158 +
  159 +- And that's it!
  160 +
  161 + > The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
  162 +
  163 +## Contributing
  164 +
  165 +Before contributing to Alamofire, please read the instructions detailed in our [contribution guide](https://github.com/Alamofire/Alamofire/blob/master/CONTRIBUTING.md).
  166 +
  167 +## Open Radars
  168 +
  169 +The following radars have some effect on the current implementation of Alamofire.
  170 +
  171 +- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in the test case
  172 +- `rdar://26870455` - Background URL Session Configurations do not work in the simulator
  173 +- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest`
  174 +
  175 +## Resolved Radars
  176 +
  177 +The following radars have been resolved over time after being filed against the Alamofire project.
  178 +
  179 +- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage.
  180 + - (Resolved): 9/1/17 in Xcode 9 beta 6.
  181 +- [`rdar://36082113`](http://openradar.appspot.com/radar?id=4942308441063424) - `URLSessionTaskMetrics` failing to link on watchOS 3.0+
  182 + - (Resolved): Just add `CFNetwork` to your linked frameworks.
  183 +- `FB7624529` - `urlSession(_:task:didFinishCollecting:)` never called on watchOS
  184 + - (Resolved): Metrics now collected on watchOS 7+.
  185 +
  186 +## FAQ
  187 +
  188 +### What's the origin of the name Alamofire?
  189 +
  190 +Alamofire is named after the [Alamo Fire flower](https://aggie-horticulture.tamu.edu/wildseed/alamofire.html), a hybrid variant of the Bluebonnet, the official state flower of Texas.
  191 +
  192 +## Credits
  193 +
  194 +Alamofire is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). You can follow them on Twitter at [@AlamofireSF](https://twitter.com/AlamofireSF) for project updates and releases.
  195 +
  196 +### Security Disclosure
  197 +
  198 +If you believe you have identified a security vulnerability with Alamofire, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker.
  199 +
  200 +## Sponsorship
  201 +
  202 +The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization.
  203 +Registering will allow Foundation members to gain some legal protections and also allow us to put donations to use, tax-free.
  204 +Sponsoring the ASF will enable us to:
  205 +
  206 +- Pay our yearly legal fees to keep the non-profit in good status
  207 +- Pay for our mail servers to help us stay on top of all questions and security issues
  208 +- Potentially fund test servers to make it easier for us to test the edge cases
  209 +- Potentially fund developers to work on one of our projects full-time
  210 +
  211 +The community adoption of the ASF libraries has been amazing.
  212 +We are greatly humbled by your enthusiasm around the projects and want to continue to do everything we can to move the needle forward.
  213 +With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members.
  214 +If you use any of our libraries for work, see if your employers would be interested in donating.
  215 +Any amount you can donate, whether once or monthly, to help us reach our goal would be greatly appreciated.
  216 +
  217 +[Sponsor Alamofire](https://github.com/sponsors/Alamofire)
  218 +
  219 +## Supporters
  220 +
  221 +[MacStadium](https://macstadium.com) provides Alamofire with a free, hosted Mac mini.
  222 +
  223 +![Powered by MacStadium](https://raw.githubusercontent.com/Alamofire/Alamofire/master/Resources/MacStadiumLogo.png)
  224 +
  225 +## License
  226 +
  227 +Alamofire is released under the MIT license. [See LICENSE](https://github.com/Alamofire/Alamofire/blob/master/LICENSE) for details.
Pods/Alamofire/Source/AFError.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/AFError.swift
  1 +//
  2 +// AFError.swift
  3 +//
  4 +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +import Foundation
  26 +
  27 +/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
  28 +/// their own associated reasons.
  29 +public enum AFError: Error {
  30 + /// The underlying reason the `.multipartEncodingFailed` error occurred.
  31 + public enum MultipartEncodingFailureReason {
  32 + /// The `fileURL` provided for reading an encodable body part isn't a file `URL`.
  33 + case bodyPartURLInvalid(url: URL)
  34 + /// The filename of the `fileURL` provided has either an empty `lastPathComponent` or `pathExtension.
  35 + case bodyPartFilenameInvalid(in: URL)
  36 + /// The file at the `fileURL` provided was not reachable.
  37 + case bodyPartFileNotReachable(at: URL)
  38 + /// Attempting to check the reachability of the `fileURL` provided threw an error.
  39 + case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
  40 + /// The file at the `fileURL` provided is actually a directory.
  41 + case bodyPartFileIsDirectory(at: URL)
  42 + /// The size of the file at the `fileURL` provided was not returned by the system.
  43 + case bodyPartFileSizeNotAvailable(at: URL)
  44 + /// The attempt to find the size of the file at the `fileURL` provided threw an error.
  45 + case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
  46 + /// An `InputStream` could not be created for the provided `fileURL`.
  47 + case bodyPartInputStreamCreationFailed(for: URL)
  48 + /// An `OutputStream` could not be created when attempting to write the encoded data to disk.
  49 + case outputStreamCreationFailed(for: URL)
  50 + /// The encoded body data could not be written to disk because a file already exists at the provided `fileURL`.
  51 + case outputStreamFileAlreadyExists(at: URL)
  52 + /// The `fileURL` provided for writing the encoded body data to disk is not a file `URL`.
  53 + case outputStreamURLInvalid(url: URL)
  54 + /// The attempt to write the encoded body data to disk failed with an underlying error.
  55 + case outputStreamWriteFailed(error: Error)
  56 + /// The attempt to read an encoded body part `InputStream` failed with underlying system error.
  57 + case inputStreamReadFailed(error: Error)
  58 + }
  59 +
  60 + /// Represents unexpected input stream length that occur when encoding the `MultipartFormData`. Instances will be
  61 + /// embedded within an `AFError.multipartEncodingFailed` `.inputStreamReadFailed` case.
  62 + public struct UnexpectedInputStreamLength: Error {
  63 + /// The expected byte count to read.
  64 + public var bytesExpected: UInt64
  65 + /// The actual byte count read.
  66 + public var bytesRead: UInt64
  67 + }
  68 +
  69 + /// The underlying reason the `.parameterEncodingFailed` error occurred.
  70 + public enum ParameterEncodingFailureReason {
  71 + /// The `URLRequest` did not have a `URL` to encode.
  72 + case missingURL
  73 + /// JSON serialization failed with an underlying system error during the encoding process.
  74 + case jsonEncodingFailed(error: Error)
  75 + /// Custom parameter encoding failed due to the associated `Error`.
  76 + case customEncodingFailed(error: Error)
  77 + }
  78 +
  79 + /// The underlying reason the `.parameterEncoderFailed` error occurred.
  80 + public enum ParameterEncoderFailureReason {
  81 + /// Possible missing components.
  82 + public enum RequiredComponent {
  83 + /// The `URL` was missing or unable to be extracted from the passed `URLRequest` or during encoding.
  84 + case url
  85 + /// The `HTTPMethod` could not be extracted from the passed `URLRequest`.
  86 + case httpMethod(rawValue: String)
  87 + }
  88 +
  89 + /// A `RequiredComponent` was missing during encoding.
  90 + case missingRequiredComponent(RequiredComponent)
  91 + /// The underlying encoder failed with the associated error.
  92 + case encoderFailed(error: Error)
  93 + }
  94 +
  95 + /// The underlying reason the `.responseValidationFailed` error occurred.
  96 + public enum ResponseValidationFailureReason {
  97 + /// The data file containing the server response did not exist.
  98 + case dataFileNil
  99 + /// The data file containing the server response at the associated `URL` could not be read.
  100 + case dataFileReadFailed(at: URL)
  101 + /// The response did not contain a `Content-Type` and the `acceptableContentTypes` provided did not contain a
  102 + /// wildcard type.
  103 + case missingContentType(acceptableContentTypes: [String])
  104 + /// The response `Content-Type` did not match any type in the provided `acceptableContentTypes`.
  105 + case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
  106 + /// The response status code was not acceptable.
  107 + case unacceptableStatusCode(code: Int)
  108 + /// Custom response validation failed due to the associated `Error`.
  109 + case customValidationFailed(error: Error)
  110 + }
  111 +
  112 + /// The underlying reason the response serialization error occurred.
  113 + public enum ResponseSerializationFailureReason {
  114 + /// The server response contained no data or the data was zero length.
  115 + case inputDataNilOrZeroLength
  116 + /// The file containing the server response did not exist.
  117 + case inputFileNil
  118 + /// The file containing the server response could not be read from the associated `URL`.
  119 + case inputFileReadFailed(at: URL)
  120 + /// String serialization failed using the provided `String.Encoding`.
  121 + case stringSerializationFailed(encoding: String.Encoding)
  122 + /// JSON serialization failed with an underlying system error.
  123 + case jsonSerializationFailed(error: Error)
  124 + /// A `DataDecoder` failed to decode the response due to the associated `Error`.
  125 + case decodingFailed(error: Error)
  126 + /// A custom response serializer failed due to the associated `Error`.
  127 + case customSerializationFailed(error: Error)
  128 + /// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
  129 + case invalidEmptyResponse(type: String)
  130 + }
  131 +
  132 + #if !(os(Linux) || os(Windows))
  133 + /// Underlying reason a server trust evaluation error occurred.
  134 + public enum ServerTrustFailureReason {
  135 + /// The output of a server trust evaluation.
  136 + public struct Output {
  137 + /// The host for which the evaluation was performed.
  138 + public let host: String
  139 + /// The `SecTrust` value which was evaluated.
  140 + public let trust: SecTrust
  141 + /// The `OSStatus` of evaluation operation.
  142 + public let status: OSStatus
  143 + /// The result of the evaluation operation.
  144 + public let result: SecTrustResultType
  145 +
  146 + /// Creates an `Output` value from the provided values.
  147 + init(_ host: String, _ trust: SecTrust, _ status: OSStatus, _ result: SecTrustResultType) {
  148 + self.host = host
  149 + self.trust = trust
  150 + self.status = status
  151 + self.result = result
  152 + }
  153 + }
  154 +
  155 + /// No `ServerTrustEvaluator` was found for the associated host.
  156 + case noRequiredEvaluator(host: String)
  157 + /// No certificates were found with which to perform the trust evaluation.
  158 + case noCertificatesFound
  159 + /// No public keys were found with which to perform the trust evaluation.
  160 + case noPublicKeysFound
  161 + /// During evaluation, application of the associated `SecPolicy` failed.
  162 + case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
  163 + /// During evaluation, setting the associated anchor certificates failed.
  164 + case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
  165 + /// During evaluation, creation of the revocation policy failed.
  166 + case revocationPolicyCreationFailed
  167 + /// `SecTrust` evaluation failed with the associated `Error`, if one was produced.
  168 + case trustEvaluationFailed(error: Error?)
  169 + /// Default evaluation failed with the associated `Output`.
  170 + case defaultEvaluationFailed(output: Output)
  171 + /// Host validation failed with the associated `Output`.
  172 + case hostValidationFailed(output: Output)
  173 + /// Revocation check failed with the associated `Output` and options.
  174 + case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
  175 + /// Certificate pinning failed.
  176 + case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
  177 + /// Public key pinning failed.
  178 + case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
  179 + /// Custom server trust evaluation failed due to the associated `Error`.
  180 + case customEvaluationFailed(error: Error)
  181 + }
  182 + #endif
  183 +
  184 + /// The underlying reason the `.urlRequestValidationFailed`
  185 + public enum URLRequestValidationFailureReason {
  186 + /// URLRequest with GET method had body data.
  187 + case bodyDataInGETRequest(Data)
  188 + }
  189 +
  190 + /// `UploadableConvertible` threw an error in `createUploadable()`.
  191 + case createUploadableFailed(error: Error)
  192 + /// `URLRequestConvertible` threw an error in `asURLRequest()`.
  193 + case createURLRequestFailed(error: Error)
  194 + /// `SessionDelegate` threw an error while attempting to move downloaded file to destination URL.
  195 + case downloadedFileMoveFailed(error: Error, source: URL, destination: URL)
  196 + /// `Request` was explicitly cancelled.
  197 + case explicitlyCancelled
  198 + /// `URLConvertible` type failed to create a valid `URL`.
  199 + case invalidURL(url: URLConvertible)
  200 + /// Multipart form encoding failed.
  201 + case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
  202 + /// `ParameterEncoding` threw an error during the encoding process.
  203 + case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
  204 + /// `ParameterEncoder` threw an error while running the encoder.
  205 + case parameterEncoderFailed(reason: ParameterEncoderFailureReason)
  206 + /// `RequestAdapter` threw an error during adaptation.
  207 + case requestAdaptationFailed(error: Error)
  208 + /// `RequestRetrier` threw an error during the request retry process.
  209 + case requestRetryFailed(retryError: Error, originalError: Error)
  210 + /// Response validation failed.
  211 + case responseValidationFailed(reason: ResponseValidationFailureReason)
  212 + /// Response serialization failed.
  213 + case responseSerializationFailed(reason: ResponseSerializationFailureReason)
  214 + #if !(os(Linux) || os(Windows))
  215 + /// `ServerTrustEvaluating` instance threw an error during trust evaluation.
  216 + case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
  217 + #endif
  218 + /// `Session` which issued the `Request` was deinitialized, most likely because its reference went out of scope.
  219 + case sessionDeinitialized
  220 + /// `Session` was explicitly invalidated, possibly with the `Error` produced by the underlying `URLSession`.
  221 + case sessionInvalidated(error: Error?)
  222 + /// `URLSessionTask` completed with error.
  223 + case sessionTaskFailed(error: Error)
  224 + /// `URLRequest` failed validation.
  225 + case urlRequestValidationFailed(reason: URLRequestValidationFailureReason)
  226 +}
  227 +
  228 +extension Error {
  229 + /// Returns the instance cast as an `AFError`.
  230 + public var asAFError: AFError? {
  231 + self as? AFError
  232 + }
  233 +
  234 + /// Returns the instance cast as an `AFError`. If casting fails, a `fatalError` with the specified `message` is thrown.
  235 + public func asAFError(orFailWith message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) -> AFError {
  236 + guard let afError = self as? AFError else {
  237 + fatalError(message(), file: file, line: line)
  238 + }
  239 + return afError
  240 + }
  241 +
  242 + /// Casts the instance as `AFError` or returns `defaultAFError`
  243 + func asAFError(or defaultAFError: @autoclosure () -> AFError) -> AFError {
  244 + self as? AFError ?? defaultAFError()
  245 + }
  246 +}
  247 +
  248 +// MARK: - Error Booleans
  249 +
  250 +extension AFError {
  251 + /// Returns whether the instance is `.sessionDeinitialized`.
  252 + public var isSessionDeinitializedError: Bool {
  253 + if case .sessionDeinitialized = self { return true }
  254 + return false
  255 + }
  256 +
  257 + /// Returns whether the instance is `.sessionInvalidated`.
  258 + public var isSessionInvalidatedError: Bool {
  259 + if case .sessionInvalidated = self { return true }
  260 + return false
  261 + }
  262 +
  263 + /// Returns whether the instance is `.explicitlyCancelled`.
  264 + public var isExplicitlyCancelledError: Bool {
  265 + if case .explicitlyCancelled = self { return true }
  266 + return false
  267 + }
  268 +
  269 + /// Returns whether the instance is `.invalidURL`.
  270 + public var isInvalidURLError: Bool {
  271 + if case .invalidURL = self { return true }
  272 + return false
  273 + }
  274 +
  275 + /// Returns whether the instance is `.parameterEncodingFailed`. When `true`, the `underlyingError` property will
  276 + /// contain the associated value.
  277 + public var isParameterEncodingError: Bool {
  278 + if case .parameterEncodingFailed = self { return true }
  279 + return false
  280 + }
  281 +
  282 + /// Returns whether the instance is `.parameterEncoderFailed`. When `true`, the `underlyingError` property will
  283 + /// contain the associated value.
  284 + public var isParameterEncoderError: Bool {
  285 + if case .parameterEncoderFailed = self { return true }
  286 + return false
  287 + }
  288 +
  289 + /// Returns whether the instance is `.multipartEncodingFailed`. When `true`, the `url` and `underlyingError`
  290 + /// properties will contain the associated values.
  291 + public var isMultipartEncodingError: Bool {
  292 + if case .multipartEncodingFailed = self { return true }
  293 + return false
  294 + }
  295 +
  296 + /// Returns whether the instance is `.requestAdaptationFailed`. When `true`, the `underlyingError` property will
  297 + /// contain the associated value.
  298 + public var isRequestAdaptationError: Bool {
  299 + if case .requestAdaptationFailed = self { return true }
  300 + return false
  301 + }
  302 +
  303 + /// Returns whether the instance is `.responseValidationFailed`. When `true`, the `acceptableContentTypes`,
  304 + /// `responseContentType`, `responseCode`, and `underlyingError` properties will contain the associated values.
  305 + public var isResponseValidationError: Bool {
  306 + if case .responseValidationFailed = self { return true }
  307 + return false
  308 + }
  309 +
  310 + /// Returns whether the instance is `.responseSerializationFailed`. When `true`, the `failedStringEncoding` and
  311 + /// `underlyingError` properties will contain the associated values.
  312 + public var isResponseSerializationError: Bool {
  313 + if case .responseSerializationFailed = self { return true }
  314 + return false
  315 + }
  316 +
  317 + #if !(os(Linux) || os(Windows))
  318 + /// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
  319 + /// contain the associated value.
  320 + public var isServerTrustEvaluationError: Bool {
  321 + if case .serverTrustEvaluationFailed = self { return true }
  322 + return false
  323 + }
  324 + #endif
  325 +
  326 + /// Returns whether the instance is `requestRetryFailed`. When `true`, the `underlyingError` property will
  327 + /// contain the associated value.
  328 + public var isRequestRetryError: Bool {
  329 + if case .requestRetryFailed = self { return true }
  330 + return false
  331 + }
  332 +
  333 + /// Returns whether the instance is `createUploadableFailed`. When `true`, the `underlyingError` property will
  334 + /// contain the associated value.
  335 + public var isCreateUploadableError: Bool {
  336 + if case .createUploadableFailed = self { return true }
  337 + return false
  338 + }
  339 +
  340 + /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
  341 + /// contain the associated value.
  342 + public var isCreateURLRequestError: Bool {
  343 + if case .createURLRequestFailed = self { return true }
  344 + return false
  345 + }
  346 +
  347 + /// Returns whether the instance is `downloadedFileMoveFailed`. When `true`, the `destination` and `underlyingError` properties will
  348 + /// contain the associated values.
  349 + public var isDownloadedFileMoveError: Bool {
  350 + if case .downloadedFileMoveFailed = self { return true }
  351 + return false
  352 + }
  353 +
  354 + /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
  355 + /// contain the associated value.
  356 + public var isSessionTaskError: Bool {
  357 + if case .sessionTaskFailed = self { return true }
  358 + return false
  359 + }
  360 +}
  361 +
  362 +// MARK: - Convenience Properties
  363 +
  364 +extension AFError {
  365 + /// The `URLConvertible` associated with the error.
  366 + public var urlConvertible: URLConvertible? {
  367 + guard case let .invalidURL(url) = self else { return nil }
  368 + return url
  369 + }
  370 +
  371 + /// The `URL` associated with the error.
  372 + public var url: URL? {
  373 + guard case let .multipartEncodingFailed(reason) = self else { return nil }
  374 + return reason.url
  375 + }
  376 +
  377 + /// The underlying `Error` responsible for generating the failure associated with `.sessionInvalidated`,
  378 + /// `.parameterEncodingFailed`, `.parameterEncoderFailed`, `.multipartEncodingFailed`, `.requestAdaptationFailed`,
  379 + /// `.responseSerializationFailed`, `.requestRetryFailed` errors.
  380 + public var underlyingError: Error? {
  381 + switch self {
  382 + case let .multipartEncodingFailed(reason):
  383 + return reason.underlyingError
  384 + case let .parameterEncodingFailed(reason):
  385 + return reason.underlyingError
  386 + case let .parameterEncoderFailed(reason):
  387 + return reason.underlyingError
  388 + case let .requestAdaptationFailed(error):
  389 + return error
  390 + case let .requestRetryFailed(retryError, _):
  391 + return retryError
  392 + case let .responseValidationFailed(reason):
  393 + return reason.underlyingError
  394 + case let .responseSerializationFailed(reason):
  395 + return reason.underlyingError
  396 + #if !(os(Linux) || os(Windows))
  397 + case let .serverTrustEvaluationFailed(reason):
  398 + return reason.underlyingError
  399 + #endif
  400 + case let .sessionInvalidated(error):
  401 + return error
  402 + case let .createUploadableFailed(error):
  403 + return error
  404 + case let .createURLRequestFailed(error):
  405 + return error
  406 + case let .downloadedFileMoveFailed(error, _, _):
  407 + return error
  408 + case let .sessionTaskFailed(error):
  409 + return error
  410 + case .explicitlyCancelled,
  411 + .invalidURL,
  412 + .sessionDeinitialized,
  413 + .urlRequestValidationFailed:
  414 + return nil
  415 + }
  416 + }
  417 +
  418 + /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
  419 + public var acceptableContentTypes: [String]? {
  420 + guard case let .responseValidationFailed(reason) = self else { return nil }
  421 + return reason.acceptableContentTypes
  422 + }
  423 +
  424 + /// The response `Content-Type` of a `.responseValidationFailed` error.
  425 + public var responseContentType: String? {
  426 + guard case let .responseValidationFailed(reason) = self else { return nil }
  427 + return reason.responseContentType
  428 + }
  429 +
  430 + /// The response code of a `.responseValidationFailed` error.
  431 + public var responseCode: Int? {
  432 + guard case let .responseValidationFailed(reason) = self else { return nil }
  433 + return reason.responseCode
  434 + }
  435 +
  436 + /// The `String.Encoding` associated with a failed `.stringResponse()` call.
  437 + public var failedStringEncoding: String.Encoding? {
  438 + guard case let .responseSerializationFailed(reason) = self else { return nil }
  439 + return reason.failedStringEncoding
  440 + }
  441 +
  442 + /// The `source` URL of a `.downloadedFileMoveFailed` error.
  443 + public var sourceURL: URL? {
  444 + guard case let .downloadedFileMoveFailed(_, source, _) = self else { return nil }
  445 + return source
  446 + }
  447 +
  448 + /// The `destination` URL of a `.downloadedFileMoveFailed` error.
  449 + public var destinationURL: URL? {
  450 + guard case let .downloadedFileMoveFailed(_, _, destination) = self else { return nil }
  451 + return destination
  452 + }
  453 +
  454 + #if !(os(Linux) || os(Windows))
  455 + /// The download resume data of any underlying network error. Only produced by `DownloadRequest`s.
  456 + public var downloadResumeData: Data? {
  457 + (underlyingError as? URLError)?.userInfo[NSURLSessionDownloadTaskResumeData] as? Data
  458 + }
  459 + #endif
  460 +}
  461 +
  462 +extension AFError.ParameterEncodingFailureReason {
  463 + var underlyingError: Error? {
  464 + switch self {
  465 + case let .jsonEncodingFailed(error),
  466 + let .customEncodingFailed(error):
  467 + return error
  468 + case .missingURL:
  469 + return nil
  470 + }
  471 + }
  472 +}
  473 +
  474 +extension AFError.ParameterEncoderFailureReason {
  475 + var underlyingError: Error? {
  476 + switch self {
  477 + case let .encoderFailed(error):
  478 + return error
  479 + case .missingRequiredComponent:
  480 + return nil
  481 + }
  482 + }
  483 +}
  484 +
  485 +extension AFError.MultipartEncodingFailureReason {
  486 + var url: URL? {
  487 + switch self {
  488 + case let .bodyPartURLInvalid(url),
  489 + let .bodyPartFilenameInvalid(url),
  490 + let .bodyPartFileNotReachable(url),
  491 + let .bodyPartFileIsDirectory(url),
  492 + let .bodyPartFileSizeNotAvailable(url),
  493 + let .bodyPartInputStreamCreationFailed(url),
  494 + let .outputStreamCreationFailed(url),
  495 + let .outputStreamFileAlreadyExists(url),
  496 + let .outputStreamURLInvalid(url),
  497 + let .bodyPartFileNotReachableWithError(url, _),
  498 + let .bodyPartFileSizeQueryFailedWithError(url, _):
  499 + return url
  500 + case .outputStreamWriteFailed,
  501 + .inputStreamReadFailed:
  502 + return nil
  503 + }
  504 + }
  505 +
  506 + var underlyingError: Error? {
  507 + switch self {
  508 + case let .bodyPartFileNotReachableWithError(_, error),
  509 + let .bodyPartFileSizeQueryFailedWithError(_, error),
  510 + let .outputStreamWriteFailed(error),
  511 + let .inputStreamReadFailed(error):
  512 + return error
  513 + case .bodyPartURLInvalid,
  514 + .bodyPartFilenameInvalid,
  515 + .bodyPartFileNotReachable,
  516 + .bodyPartFileIsDirectory,
  517 + .bodyPartFileSizeNotAvailable,
  518 + .bodyPartInputStreamCreationFailed,
  519 + .outputStreamCreationFailed,
  520 + .outputStreamFileAlreadyExists,
  521 + .outputStreamURLInvalid:
  522 + return nil
  523 + }
  524 + }
  525 +}
  526 +
  527 +extension AFError.ResponseValidationFailureReason {
  528 + var acceptableContentTypes: [String]? {
  529 + switch self {
  530 + case let .missingContentType(types),
  531 + let .unacceptableContentType(types, _):
  532 + return types
  533 + case .dataFileNil,
  534 + .dataFileReadFailed,
  535 + .unacceptableStatusCode,
  536 + .customValidationFailed:
  537 + return nil
  538 + }
  539 + }
  540 +
  541 + var responseContentType: String? {
  542 + switch self {
  543 + case let .unacceptableContentType(_, responseType):
  544 + return responseType
  545 + case .dataFileNil,
  546 + .dataFileReadFailed,
  547 + .missingContentType,
  548 + .unacceptableStatusCode,
  549 + .customValidationFailed:
  550 + return nil
  551 + }
  552 + }
  553 +
  554 + var responseCode: Int? {
  555 + switch self {
  556 + case let .unacceptableStatusCode(code):
  557 + return code
  558 + case .dataFileNil,
  559 + .dataFileReadFailed,
  560 + .missingContentType,
  561 + .unacceptableContentType,
  562 + .customValidationFailed:
  563 + return nil
  564 + }
  565 + }
  566 +
  567 + var underlyingError: Error? {
  568 + switch self {
  569 + case let .customValidationFailed(error):
  570 + return error
  571 + case .dataFileNil,
  572 + .dataFileReadFailed,
  573 + .missingContentType,
  574 + .unacceptableContentType,
  575 + .unacceptableStatusCode:
  576 + return nil
  577 + }
  578 + }
  579 +}
  580 +
  581 +extension AFError.ResponseSerializationFailureReason {
  582 + var failedStringEncoding: String.Encoding? {
  583 + switch self {
  584 + case let .stringSerializationFailed(encoding):
  585 + return encoding
  586 + case .inputDataNilOrZeroLength,
  587 + .inputFileNil,
  588 + .inputFileReadFailed(_),
  589 + .jsonSerializationFailed(_),
  590 + .decodingFailed(_),
  591 + .customSerializationFailed(_),
  592 + .invalidEmptyResponse:
  593 + return nil
  594 + }
  595 + }
  596 +
  597 + var underlyingError: Error? {
  598 + switch self {
  599 + case let .jsonSerializationFailed(error),
  600 + let .decodingFailed(error),
  601 + let .customSerializationFailed(error):
  602 + return error
  603 + case .inputDataNilOrZeroLength,
  604 + .inputFileNil,
  605 + .inputFileReadFailed,
  606 + .stringSerializationFailed,
  607 + .invalidEmptyResponse:
  608 + return nil
  609 + }
  610 + }
  611 +}
  612 +
  613 +#if !(os(Linux) || os(Windows))
  614 +extension AFError.ServerTrustFailureReason {
  615 + var output: AFError.ServerTrustFailureReason.Output? {
  616 + switch self {
  617 + case let .defaultEvaluationFailed(output),
  618 + let .hostValidationFailed(output),
  619 + let .revocationCheckFailed(output, _):
  620 + return output
  621 + case .noRequiredEvaluator,
  622 + .noCertificatesFound,
  623 + .noPublicKeysFound,
  624 + .policyApplicationFailed,
  625 + .settingAnchorCertificatesFailed,
  626 + .revocationPolicyCreationFailed,
  627 + .trustEvaluationFailed,
  628 + .certificatePinningFailed,
  629 + .publicKeyPinningFailed,
  630 + .customEvaluationFailed:
  631 + return nil
  632 + }
  633 + }
  634 +
  635 + var underlyingError: Error? {
  636 + switch self {
  637 + case let .customEvaluationFailed(error):
  638 + return error
  639 + case let .trustEvaluationFailed(error):
  640 + return error
  641 + case .noRequiredEvaluator,
  642 + .noCertificatesFound,
  643 + .noPublicKeysFound,
  644 + .policyApplicationFailed,
  645 + .settingAnchorCertificatesFailed,
  646 + .revocationPolicyCreationFailed,
  647 + .defaultEvaluationFailed,
  648 + .hostValidationFailed,
  649 + .revocationCheckFailed,
  650 + .certificatePinningFailed,
  651 + .publicKeyPinningFailed:
  652 + return nil
  653 + }
  654 + }
  655 +}
  656 +#endif
  657 +
  658 +// MARK: - Error Descriptions
  659 +
  660 +extension AFError: LocalizedError {
  661 + public var errorDescription: String? {
  662 + switch self {
  663 + case .explicitlyCancelled:
  664 + return "Request explicitly cancelled."
  665 + case let .invalidURL(url):
  666 + return "URL is not valid: \(url)"
  667 + case let .parameterEncodingFailed(reason):
  668 + return reason.localizedDescription
  669 + case let .parameterEncoderFailed(reason):
  670 + return reason.localizedDescription
  671 + case let .multipartEncodingFailed(reason):
  672 + return reason.localizedDescription
  673 + case let .requestAdaptationFailed(error):
  674 + return "Request adaption failed with error: \(error.localizedDescription)"
  675 + case let .responseValidationFailed(reason):
  676 + return reason.localizedDescription
  677 + case let .responseSerializationFailed(reason):
  678 + return reason.localizedDescription
  679 + case let .requestRetryFailed(retryError, originalError):
  680 + return """
  681 + Request retry failed with retry error: \(retryError.localizedDescription), \
  682 + original error: \(originalError.localizedDescription)
  683 + """
  684 + case .sessionDeinitialized:
  685 + return """
  686 + Session was invalidated without error, so it was likely deinitialized unexpectedly. \
  687 + Be sure to retain a reference to your Session for the duration of your requests.
  688 + """
  689 + case let .sessionInvalidated(error):
  690 + return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
  691 + #if !(os(Linux) || os(Windows))
  692 + case let .serverTrustEvaluationFailed(reason):
  693 + return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
  694 + #endif
  695 + case let .urlRequestValidationFailed(reason):
  696 + return "URLRequest validation failed due to reason: \(reason.localizedDescription)"
  697 + case let .createUploadableFailed(error):
  698 + return "Uploadable creation failed with error: \(error.localizedDescription)"
  699 + case let .createURLRequestFailed(error):
  700 + return "URLRequest creation failed with error: \(error.localizedDescription)"
  701 + case let .downloadedFileMoveFailed(error, source, destination):
  702 + return "Moving downloaded file from: \(source) to: \(destination) failed with error: \(error.localizedDescription)"
  703 + case let .sessionTaskFailed(error):
  704 + return "URLSessionTask failed with error: \(error.localizedDescription)"
  705 + }
  706 + }
  707 +}
  708 +
  709 +extension AFError.ParameterEncodingFailureReason {
  710 + var localizedDescription: String {
  711 + switch self {
  712 + case .missingURL:
  713 + return "URL request to encode was missing a URL"
  714 + case let .jsonEncodingFailed(error):
  715 + return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
  716 + case let .customEncodingFailed(error):
  717 + return "Custom parameter encoder failed with error: \(error.localizedDescription)"
  718 + }
  719 + }
  720 +}
  721 +
  722 +extension AFError.ParameterEncoderFailureReason {
  723 + var localizedDescription: String {
  724 + switch self {
  725 + case let .missingRequiredComponent(component):
  726 + return "Encoding failed due to a missing request component: \(component)"
  727 + case let .encoderFailed(error):
  728 + return "The underlying encoder failed with the error: \(error)"
  729 + }
  730 + }
  731 +}
  732 +
  733 +extension AFError.MultipartEncodingFailureReason {
  734 + var localizedDescription: String {
  735 + switch self {
  736 + case let .bodyPartURLInvalid(url):
  737 + return "The URL provided is not a file URL: \(url)"
  738 + case let .bodyPartFilenameInvalid(url):
  739 + return "The URL provided does not have a valid filename: \(url)"
  740 + case let .bodyPartFileNotReachable(url):
  741 + return "The URL provided is not reachable: \(url)"
  742 + case let .bodyPartFileNotReachableWithError(url, error):
  743 + return """
  744 + The system returned an error while checking the provided URL for reachability.
  745 + URL: \(url)
  746 + Error: \(error)
  747 + """
  748 + case let .bodyPartFileIsDirectory(url):
  749 + return "The URL provided is a directory: \(url)"
  750 + case let .bodyPartFileSizeNotAvailable(url):
  751 + return "Could not fetch the file size from the provided URL: \(url)"
  752 + case let .bodyPartFileSizeQueryFailedWithError(url, error):
  753 + return """
  754 + The system returned an error while attempting to fetch the file size from the provided URL.
  755 + URL: \(url)
  756 + Error: \(error)
  757 + """
  758 + case let .bodyPartInputStreamCreationFailed(url):
  759 + return "Failed to create an InputStream for the provided URL: \(url)"
  760 + case let .outputStreamCreationFailed(url):
  761 + return "Failed to create an OutputStream for URL: \(url)"
  762 + case let .outputStreamFileAlreadyExists(url):
  763 + return "A file already exists at the provided URL: \(url)"
  764 + case let .outputStreamURLInvalid(url):
  765 + return "The provided OutputStream URL is invalid: \(url)"
  766 + case let .outputStreamWriteFailed(error):
  767 + return "OutputStream write failed with error: \(error)"
  768 + case let .inputStreamReadFailed(error):
  769 + return "InputStream read failed with error: \(error)"
  770 + }
  771 + }
  772 +}
  773 +
  774 +extension AFError.ResponseSerializationFailureReason {
  775 + var localizedDescription: String {
  776 + switch self {
  777 + case .inputDataNilOrZeroLength:
  778 + return "Response could not be serialized, input data was nil or zero length."
  779 + case .inputFileNil:
  780 + return "Response could not be serialized, input file was nil."
  781 + case let .inputFileReadFailed(url):
  782 + return "Response could not be serialized, input file could not be read: \(url)."
  783 + case let .stringSerializationFailed(encoding):
  784 + return "String could not be serialized with encoding: \(encoding)."
  785 + case let .jsonSerializationFailed(error):
  786 + return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
  787 + case let .invalidEmptyResponse(type):
  788 + return """
  789 + Empty response could not be serialized to type: \(type). \
  790 + Use Empty as the expected type for such responses.
  791 + """
  792 + case let .decodingFailed(error):
  793 + return "Response could not be decoded because of error:\n\(error.localizedDescription)"
  794 + case let .customSerializationFailed(error):
  795 + return "Custom response serializer failed with error:\n\(error.localizedDescription)"
  796 + }
  797 + }
  798 +}
  799 +
  800 +extension AFError.ResponseValidationFailureReason {
  801 + var localizedDescription: String {
  802 + switch self {
  803 + case .dataFileNil:
  804 + return "Response could not be validated, data file was nil."
  805 + case let .dataFileReadFailed(url):
  806 + return "Response could not be validated, data file could not be read: \(url)."
  807 + case let .missingContentType(types):
  808 + return """
  809 + Response Content-Type was missing and acceptable content types \
  810 + (\(types.joined(separator: ","))) do not match "*/*".
  811 + """
  812 + case let .unacceptableContentType(acceptableTypes, responseType):
  813 + return """
  814 + Response Content-Type "\(responseType)" does not match any acceptable types: \
  815 + \(acceptableTypes.joined(separator: ",")).
  816 + """
  817 + case let .unacceptableStatusCode(code):
  818 + return "Response status code was unacceptable: \(code)."
  819 + case let .customValidationFailed(error):
  820 + return "Custom response validation failed with error: \(error.localizedDescription)"
  821 + }
  822 + }
  823 +}
  824 +
  825 +#if !(os(Linux) || os(Windows))
  826 +extension AFError.ServerTrustFailureReason {
  827 + var localizedDescription: String {
  828 + switch self {
  829 + case let .noRequiredEvaluator(host):
  830 + return "A ServerTrustEvaluating value is required for host \(host) but none was found."
  831 + case .noCertificatesFound:
  832 + return "No certificates were found or provided for evaluation."
  833 + case .noPublicKeysFound:
  834 + return "No public keys were found or provided for evaluation."
  835 + case .policyApplicationFailed:
  836 + return "Attempting to set a SecPolicy failed."
  837 + case .settingAnchorCertificatesFailed:
  838 + return "Attempting to set the provided certificates as anchor certificates failed."
  839 + case .revocationPolicyCreationFailed:
  840 + return "Attempting to create a revocation policy failed."
  841 + case let .trustEvaluationFailed(error):
  842 + return "SecTrust evaluation failed with error: \(error?.localizedDescription ?? "None")"
  843 + case let .defaultEvaluationFailed(output):
  844 + return "Default evaluation failed for host \(output.host)."
  845 + case let .hostValidationFailed(output):
  846 + return "Host validation failed for host \(output.host)."
  847 + case let .revocationCheckFailed(output, _):
  848 + return "Revocation check failed for host \(output.host)."
  849 + case let .certificatePinningFailed(host, _, _, _):
  850 + return "Certificate pinning failed for host \(host)."
  851 + case let .publicKeyPinningFailed(host, _, _, _):
  852 + return "Public key pinning failed for host \(host)."
  853 + case let .customEvaluationFailed(error):
  854 + return "Custom trust evaluation failed with error: \(error.localizedDescription)"
  855 + }
  856 + }
  857 +}
  858 +#endif
  859 +
  860 +extension AFError.URLRequestValidationFailureReason {
  861 + var localizedDescription: String {
  862 + switch self {
  863 + case let .bodyDataInGETRequest(data):
  864 + return """
  865 + Invalid URLRequest: Requests with GET method cannot have body data:
  866 + \(String(decoding: data, as: UTF8.self))
  867 + """
  868 + }
  869 + }
  870 +}
Pods/Alamofire/Source/Alamofire.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/Alamofire.swift
  1 +//
  2 +// Alamofire.swift
  3 +//
  4 +// Copyright (c) 2014-2021 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +import Dispatch
  26 +import Foundation
  27 +#if canImport(FoundationNetworking)
  28 +@_exported import FoundationNetworking
  29 +#endif
  30 +
  31 +// Enforce minimum Swift version for all platforms and build systems.
  32 +#if swift(<5.5)
  33 +#error("Alamofire doesn't support Swift versions below 5.5.")
  34 +#endif
  35 +
  36 +/// Reference to `Session.default` for quick bootstrapping and examples.
  37 +public let AF = Session.default
  38 +
  39 +/// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
  40 +let version = "5.7.1"
Pods/Alamofire/Source/AlamofireExtended.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/AlamofireExtended.swift
  1 +//
  2 +// AlamofireExtended.swift
  3 +//
  4 +// Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +/// Type that acts as a generic extension point for all `AlamofireExtended` types.
  26 +public struct AlamofireExtension<ExtendedType> {
  27 + /// Stores the type or meta-type of any extended type.
  28 + public private(set) var type: ExtendedType
  29 +
  30 + /// Create an instance from the provided value.
  31 + ///
  32 + /// - Parameter type: Instance being extended.
  33 + public init(_ type: ExtendedType) {
  34 + self.type = type
  35 + }
  36 +}
  37 +
  38 +/// Protocol describing the `af` extension points for Alamofire extended types.
  39 +public protocol AlamofireExtended {
  40 + /// Type being extended.
  41 + associatedtype ExtendedType
  42 +
  43 + /// Static Alamofire extension point.
  44 + static var af: AlamofireExtension<ExtendedType>.Type { get set }
  45 + /// Instance Alamofire extension point.
  46 + var af: AlamofireExtension<ExtendedType> { get set }
  47 +}
  48 +
  49 +extension AlamofireExtended {
  50 + /// Static Alamofire extension point.
  51 + public static var af: AlamofireExtension<Self>.Type {
  52 + get { AlamofireExtension<Self>.self }
  53 + set {}
  54 + }
  55 +
  56 + /// Instance Alamofire extension point.
  57 + public var af: AlamofireExtension<Self> {
  58 + get { AlamofireExtension(self) }
  59 + set {}
  60 + }
  61 +}
Pods/Alamofire/Source/AuthenticationInterceptor.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/AuthenticationInterceptor.swift
  1 +//
  2 +// AuthenticationInterceptor.swift
  3 +//
  4 +// Copyright (c) 2020 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +import Foundation
  26 +
  27 +/// Types adopting the `AuthenticationCredential` protocol can be used to authenticate `URLRequest`s.
  28 +///
  29 +/// One common example of an `AuthenticationCredential` is an OAuth2 credential containing an access token used to
  30 +/// authenticate all requests on behalf of a user. The access token generally has an expiration window of 60 minutes
  31 +/// which will then require a refresh of the credential using the refresh token to generate a new access token.
  32 +public protocol AuthenticationCredential {
  33 + /// Whether the credential requires a refresh. This property should always return `true` when the credential is
  34 + /// expired. It is also wise to consider returning `true` when the credential will expire in several seconds or
  35 + /// minutes depending on the expiration window of the credential.
  36 + ///
  37 + /// For example, if the credential is valid for 60 minutes, then it would be wise to return `true` when the
  38 + /// credential is only valid for 5 minutes or less. That ensures the credential will not expire as it is passed
  39 + /// around backend services.
  40 + var requiresRefresh: Bool { get }
  41 +}
  42 +
  43 +// MARK: -
  44 +
  45 +/// Types adopting the `Authenticator` protocol can be used to authenticate `URLRequest`s with an
  46 +/// `AuthenticationCredential` as well as refresh the `AuthenticationCredential` when required.
  47 +public protocol Authenticator: AnyObject {
  48 + /// The type of credential associated with the `Authenticator` instance.
  49 + associatedtype Credential: AuthenticationCredential
  50 +
  51 + /// Applies the `Credential` to the `URLRequest`.
  52 + ///
  53 + /// In the case of OAuth2, the access token of the `Credential` would be added to the `URLRequest` as a Bearer
  54 + /// token to the `Authorization` header.
  55 + ///
  56 + /// - Parameters:
  57 + /// - credential: The `Credential`.
  58 + /// - urlRequest: The `URLRequest`.
  59 + func apply(_ credential: Credential, to urlRequest: inout URLRequest)
  60 +
  61 + /// Refreshes the `Credential` and executes the `completion` closure with the `Result` once complete.
  62 + ///
  63 + /// Refresh can be called in one of two ways. It can be called before the `Request` is actually executed due to
  64 + /// a `requiresRefresh` returning `true` during the adapt portion of the `Request` creation process. It can also
  65 + /// be triggered by a failed `Request` where the authentication server denied access due to an expired or
  66 + /// invalidated access token.
  67 + ///
  68 + /// In the case of OAuth2, this method would use the refresh token of the `Credential` to generate a new
  69 + /// `Credential` using the authentication service. Once complete, the `completion` closure should be called with
  70 + /// the new `Credential`, or the error that occurred.
  71 + ///
  72 + /// In general, if the refresh call fails with certain status codes from the authentication server (commonly a 401),
  73 + /// the refresh token in the `Credential` can no longer be used to generate a valid `Credential`. In these cases,
  74 + /// you will need to reauthenticate the user with their username / password.
  75 + ///
  76 + /// Please note, these are just general examples of common use cases. They are not meant to solve your specific
  77 + /// authentication server challenges. Please work with your authentication server team to ensure your
  78 + /// `Authenticator` logic matches their expectations.
  79 + ///
  80 + /// - Parameters:
  81 + /// - credential: The `Credential` to refresh.
  82 + /// - session: The `Session` requiring the refresh.
  83 + /// - completion: The closure to be executed once the refresh is complete.
  84 + func refresh(_ credential: Credential, for session: Session, completion: @escaping (Result<Credential, Error>) -> Void)
  85 +
  86 + /// Determines whether the `URLRequest` failed due to an authentication error based on the `HTTPURLResponse`.
  87 + ///
  88 + /// If the authentication server **CANNOT** invalidate credentials after they are issued, then simply return `false`
  89 + /// for this method. If the authentication server **CAN** invalidate credentials due to security breaches, then you
  90 + /// will need to work with your authentication server team to understand how to identify when this occurs.
  91 + ///
  92 + /// In the case of OAuth2, where an authentication server can invalidate credentials, you will need to inspect the
  93 + /// `HTTPURLResponse` or possibly the `Error` for when this occurs. This is commonly handled by the authentication
  94 + /// server returning a 401 status code and some additional header to indicate an OAuth2 failure occurred.
  95 + ///
  96 + /// It is very important to understand how your authentication server works to be able to implement this correctly.
  97 + /// For example, if your authentication server returns a 401 when an OAuth2 error occurs, and your downstream
  98 + /// service also returns a 401 when you are not authorized to perform that operation, how do you know which layer
  99 + /// of the backend returned you a 401? You do not want to trigger a refresh unless you know your authentication
  100 + /// server is actually the layer rejecting the request. Again, work with your authentication server team to understand
  101 + /// how to identify an OAuth2 401 error vs. a downstream 401 error to avoid endless refresh loops.
  102 + ///
  103 + /// - Parameters:
  104 + /// - urlRequest: The `URLRequest`.
  105 + /// - response: The `HTTPURLResponse`.
  106 + /// - error: The `Error`.
  107 + ///
  108 + /// - Returns: `true` if the `URLRequest` failed due to an authentication error, `false` otherwise.
  109 + func didRequest(_ urlRequest: URLRequest, with response: HTTPURLResponse, failDueToAuthenticationError error: Error) -> Bool
  110 +
  111 + /// Determines whether the `URLRequest` is authenticated with the `Credential`.
  112 + ///
  113 + /// If the authentication server **CANNOT** invalidate credentials after they are issued, then simply return `true`
  114 + /// for this method. If the authentication server **CAN** invalidate credentials due to security breaches, then
  115 + /// read on.
  116 + ///
  117 + /// When an authentication server can invalidate credentials, it means that you may have a non-expired credential
  118 + /// that appears to be valid, but will be rejected by the authentication server when used. Generally when this
  119 + /// happens, a number of requests are all sent when the application is foregrounded, and all of them will be
  120 + /// rejected by the authentication server in the order they are received. The first failed request will trigger a
  121 + /// refresh internally, which will update the credential, and then retry all the queued requests with the new
  122 + /// credential. However, it is possible that some of the original requests will not return from the authentication
  123 + /// server until the refresh has completed. This is where this method comes in.
  124 + ///
  125 + /// When the authentication server rejects a credential, we need to check to make sure we haven't refreshed the
  126 + /// credential while the request was in flight. If it has already refreshed, then we don't need to trigger an
  127 + /// additional refresh. If it hasn't refreshed, then we need to refresh.
  128 + ///
  129 + /// Now that it is understood how the result of this method is used in the refresh lifecyle, let's walk through how
  130 + /// to implement it. You should return `true` in this method if the `URLRequest` is authenticated in a way that
  131 + /// matches the values in the `Credential`. In the case of OAuth2, this would mean that the Bearer token in the
  132 + /// `Authorization` header of the `URLRequest` matches the access token in the `Credential`. If it matches, then we
  133 + /// know the `Credential` was used to authenticate the `URLRequest` and should return `true`. If the Bearer token
  134 + /// did not match the access token, then you should return `false`.
  135 + ///
  136 + /// - Parameters:
  137 + /// - urlRequest: The `URLRequest`.
  138 + /// - credential: The `Credential`.
  139 + ///
  140 + /// - Returns: `true` if the `URLRequest` is authenticated with the `Credential`, `false` otherwise.
  141 + func isRequest(_ urlRequest: URLRequest, authenticatedWith credential: Credential) -> Bool
  142 +}
  143 +
  144 +// MARK: -
  145 +
  146 +/// Represents various authentication failures that occur when using the `AuthenticationInterceptor`. All errors are
  147 +/// still vended from Alamofire as `AFError` types. The `AuthenticationError` instances will be embedded within
  148 +/// `AFError` `.requestAdaptationFailed` or `.requestRetryFailed` cases.
  149 +public enum AuthenticationError: Error {
  150 + /// The credential was missing so the request could not be authenticated.
  151 + case missingCredential
  152 + /// The credential was refreshed too many times within the `RefreshWindow`.
  153 + case excessiveRefresh
  154 +}
  155 +
  156 +// MARK: -
  157 +
  158 +/// The `AuthenticationInterceptor` class manages the queuing and threading complexity of authenticating requests.
  159 +/// It relies on an `Authenticator` type to handle the actual `URLRequest` authentication and `Credential` refresh.
  160 +public class AuthenticationInterceptor<AuthenticatorType>: RequestInterceptor where AuthenticatorType: Authenticator {
  161 + // MARK: Typealiases
  162 +
  163 + /// Type of credential used to authenticate requests.
  164 + public typealias Credential = AuthenticatorType.Credential
  165 +
  166 + // MARK: Helper Types
  167 +
  168 + /// Type that defines a time window used to identify excessive refresh calls. When enabled, prior to executing a
  169 + /// refresh, the `AuthenticationInterceptor` compares the timestamp history of previous refresh calls against the
  170 + /// `RefreshWindow`. If more refreshes have occurred within the refresh window than allowed, the refresh is
  171 + /// cancelled and an `AuthorizationError.excessiveRefresh` error is thrown.
  172 + public struct RefreshWindow {
  173 + /// `TimeInterval` defining the duration of the time window before the current time in which the number of
  174 + /// refresh attempts is compared against `maximumAttempts`. For example, if `interval` is 30 seconds, then the
  175 + /// `RefreshWindow` represents the past 30 seconds. If more attempts occurred in the past 30 seconds than
  176 + /// `maximumAttempts`, an `.excessiveRefresh` error will be thrown.
  177 + public let interval: TimeInterval
  178 +
  179 + /// Total refresh attempts allowed within `interval` before throwing an `.excessiveRefresh` error.
  180 + public let maximumAttempts: Int
  181 +
  182 + /// Creates a `RefreshWindow` instance from the specified `interval` and `maximumAttempts`.
  183 + ///
  184 + /// - Parameters:
  185 + /// - interval: `TimeInterval` defining the duration of the time window before the current time.
  186 + /// - maximumAttempts: The maximum attempts allowed within the `TimeInterval`.
  187 + public init(interval: TimeInterval = 30.0, maximumAttempts: Int = 5) {
  188 + self.interval = interval
  189 + self.maximumAttempts = maximumAttempts
  190 + }
  191 + }
  192 +
  193 + private struct AdaptOperation {
  194 + let urlRequest: URLRequest
  195 + let session: Session
  196 + let completion: (Result<URLRequest, Error>) -> Void
  197 + }
  198 +
  199 + private enum AdaptResult {
  200 + case adapt(Credential)
  201 + case doNotAdapt(AuthenticationError)
  202 + case adaptDeferred
  203 + }
  204 +
  205 + private struct MutableState {
  206 + var credential: Credential?
  207 +
  208 + var isRefreshing = false
  209 + var refreshTimestamps: [TimeInterval] = []
  210 + var refreshWindow: RefreshWindow?
  211 +
  212 + var adaptOperations: [AdaptOperation] = []
  213 + var requestsToRetry: [(RetryResult) -> Void] = []
  214 + }
  215 +
  216 + // MARK: Properties
  217 +
  218 + /// The `Credential` used to authenticate requests.
  219 + public var credential: Credential? {
  220 + get { $mutableState.credential }
  221 + set { $mutableState.credential = newValue }
  222 + }
  223 +
  224 + let authenticator: AuthenticatorType
  225 + let queue = DispatchQueue(label: "org.alamofire.authentication.inspector")
  226 +
  227 + @Protected
  228 + private var mutableState: MutableState
  229 +
  230 + // MARK: Initialization
  231 +
  232 + /// Creates an `AuthenticationInterceptor` instance from the specified parameters.
  233 + ///
  234 + /// A `nil` `RefreshWindow` will result in the `AuthenticationInterceptor` not checking for excessive refresh calls.
  235 + /// It is recommended to always use a `RefreshWindow` to avoid endless refresh cycles.
  236 + ///
  237 + /// - Parameters:
  238 + /// - authenticator: The `Authenticator` type.
  239 + /// - credential: The `Credential` if it exists. `nil` by default.
  240 + /// - refreshWindow: The `RefreshWindow` used to identify excessive refresh calls. `RefreshWindow()` by default.
  241 + public init(authenticator: AuthenticatorType,
  242 + credential: Credential? = nil,
  243 + refreshWindow: RefreshWindow? = RefreshWindow()) {
  244 + self.authenticator = authenticator
  245 + mutableState = MutableState(credential: credential, refreshWindow: refreshWindow)
  246 + }
  247 +
  248 + // MARK: Adapt
  249 +
  250 + public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
  251 + let adaptResult: AdaptResult = $mutableState.write { mutableState in
  252 + // Queue the adapt operation if a refresh is already in place.
  253 + guard !mutableState.isRefreshing else {
  254 + let operation = AdaptOperation(urlRequest: urlRequest, session: session, completion: completion)
  255 + mutableState.adaptOperations.append(operation)
  256 + return .adaptDeferred
  257 + }
  258 +
  259 + // Throw missing credential error is the credential is missing.
  260 + guard let credential = mutableState.credential else {
  261 + let error = AuthenticationError.missingCredential
  262 + return .doNotAdapt(error)
  263 + }
  264 +
  265 + // Queue the adapt operation and trigger refresh operation if credential requires refresh.
  266 + guard !credential.requiresRefresh else {
  267 + let operation = AdaptOperation(urlRequest: urlRequest, session: session, completion: completion)
  268 + mutableState.adaptOperations.append(operation)
  269 + refresh(credential, for: session, insideLock: &mutableState)
  270 + return .adaptDeferred
  271 + }
  272 +
  273 + return .adapt(credential)
  274 + }
  275 +
  276 + switch adaptResult {
  277 + case let .adapt(credential):
  278 + var authenticatedRequest = urlRequest
  279 + authenticator.apply(credential, to: &authenticatedRequest)
  280 + completion(.success(authenticatedRequest))
  281 +
  282 + case let .doNotAdapt(adaptError):
  283 + completion(.failure(adaptError))
  284 +
  285 + case .adaptDeferred:
  286 + // No-op: adapt operation captured during refresh.
  287 + break
  288 + }
  289 + }
  290 +
  291 + // MARK: Retry
  292 +
  293 + public func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
  294 + // Do not attempt retry if there was not an original request and response from the server.
  295 + guard let urlRequest = request.request, let response = request.response else {
  296 + completion(.doNotRetry)
  297 + return
  298 + }
  299 +
  300 + // Do not attempt retry unless the `Authenticator` verifies failure was due to authentication error (i.e. 401 status code).
  301 + guard authenticator.didRequest(urlRequest, with: response, failDueToAuthenticationError: error) else {
  302 + completion(.doNotRetry)
  303 + return
  304 + }
  305 +
  306 + // Do not attempt retry if there is no credential.
  307 + guard let credential = credential else {
  308 + let error = AuthenticationError.missingCredential
  309 + completion(.doNotRetryWithError(error))
  310 + return
  311 + }
  312 +
  313 + // Retry the request if the `Authenticator` verifies it was authenticated with a previous credential.
  314 + guard authenticator.isRequest(urlRequest, authenticatedWith: credential) else {
  315 + completion(.retry)
  316 + return
  317 + }
  318 +
  319 + $mutableState.write { mutableState in
  320 + mutableState.requestsToRetry.append(completion)
  321 +
  322 + guard !mutableState.isRefreshing else { return }
  323 +
  324 + refresh(credential, for: session, insideLock: &mutableState)
  325 + }
  326 + }
  327 +
  328 + // MARK: Refresh
  329 +
  330 + private func refresh(_ credential: Credential, for session: Session, insideLock mutableState: inout MutableState) {
  331 + guard !isRefreshExcessive(insideLock: &mutableState) else {
  332 + let error = AuthenticationError.excessiveRefresh
  333 + handleRefreshFailure(error, insideLock: &mutableState)
  334 + return
  335 + }
  336 +
  337 + mutableState.refreshTimestamps.append(ProcessInfo.processInfo.systemUptime)
  338 + mutableState.isRefreshing = true
  339 +
  340 + // Dispatch to queue to hop out of the lock in case authenticator.refresh is implemented synchronously.
  341 + queue.async {
  342 + self.authenticator.refresh(credential, for: session) { result in
  343 + self.$mutableState.write { mutableState in
  344 + switch result {
  345 + case let .success(credential):
  346 + self.handleRefreshSuccess(credential, insideLock: &mutableState)
  347 + case let .failure(error):
  348 + self.handleRefreshFailure(error, insideLock: &mutableState)
  349 + }
  350 + }
  351 + }
  352 + }
  353 + }
  354 +
  355 + private func isRefreshExcessive(insideLock mutableState: inout MutableState) -> Bool {
  356 + guard let refreshWindow = mutableState.refreshWindow else { return false }
  357 +
  358 + let refreshWindowMin = ProcessInfo.processInfo.systemUptime - refreshWindow.interval
  359 +
  360 + let refreshAttemptsWithinWindow = mutableState.refreshTimestamps.reduce(into: 0) { attempts, refreshTimestamp in
  361 + guard refreshWindowMin <= refreshTimestamp else { return }
  362 + attempts += 1
  363 + }
  364 +
  365 + let isRefreshExcessive = refreshAttemptsWithinWindow >= refreshWindow.maximumAttempts
  366 +
  367 + return isRefreshExcessive
  368 + }
  369 +
  370 + private func handleRefreshSuccess(_ credential: Credential, insideLock mutableState: inout MutableState) {
  371 + mutableState.credential = credential
  372 +
  373 + let adaptOperations = mutableState.adaptOperations
  374 + let requestsToRetry = mutableState.requestsToRetry
  375 +
  376 + mutableState.adaptOperations.removeAll()
  377 + mutableState.requestsToRetry.removeAll()
  378 +
  379 + mutableState.isRefreshing = false
  380 +
  381 + // Dispatch to queue to hop out of the mutable state lock
  382 + queue.async {
  383 + adaptOperations.forEach { self.adapt($0.urlRequest, for: $0.session, completion: $0.completion) }
  384 + requestsToRetry.forEach { $0(.retry) }
  385 + }
  386 + }
  387 +
  388 + private func handleRefreshFailure(_ error: Error, insideLock mutableState: inout MutableState) {
  389 + let adaptOperations = mutableState.adaptOperations
  390 + let requestsToRetry = mutableState.requestsToRetry
  391 +
  392 + mutableState.adaptOperations.removeAll()
  393 + mutableState.requestsToRetry.removeAll()
  394 +
  395 + mutableState.isRefreshing = false
  396 +
  397 + // Dispatch to queue to hop out of the mutable state lock
  398 + queue.async {
  399 + adaptOperations.forEach { $0.completion(.failure(error)) }
  400 + requestsToRetry.forEach { $0(.doNotRetryWithError(error)) }
  401 + }
  402 + }
  403 +}
Pods/Alamofire/Source/CachedResponseHandler.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/CachedResponseHandler.swift
  1 +//
  2 +// CachedResponseHandler.swift
  3 +//
  4 +// Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +import Foundation
  26 +
  27 +/// A type that handles whether the data task should store the HTTP response in the cache.
  28 +public protocol CachedResponseHandler {
  29 + /// Determines whether the HTTP response should be stored in the cache.
  30 + ///
  31 + /// The `completion` closure should be passed one of three possible options:
  32 + ///
  33 + /// 1. The cached response provided by the server (this is the most common use case).
  34 + /// 2. A modified version of the cached response (you may want to modify it in some way before caching).
  35 + /// 3. A `nil` value to prevent the cached response from being stored in the cache.
  36 + ///
  37 + /// - Parameters:
  38 + /// - task: The data task whose request resulted in the cached response.
  39 + /// - response: The cached response to potentially store in the cache.
  40 + /// - completion: The closure to execute containing cached response, a modified response, or `nil`.
  41 + func dataTask(_ task: URLSessionDataTask,
  42 + willCacheResponse response: CachedURLResponse,
  43 + completion: @escaping (CachedURLResponse?) -> Void)
  44 +}
  45 +
  46 +// MARK: -
  47 +
  48 +/// `ResponseCacher` is a convenience `CachedResponseHandler` making it easy to cache, not cache, or modify a cached
  49 +/// response.
  50 +public struct ResponseCacher {
  51 + /// Defines the behavior of the `ResponseCacher` type.
  52 + public enum Behavior {
  53 + /// Stores the cached response in the cache.
  54 + case cache
  55 + /// Prevents the cached response from being stored in the cache.
  56 + case doNotCache
  57 + /// Modifies the cached response before storing it in the cache.
  58 + case modify((URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)
  59 + }
  60 +
  61 + /// Returns a `ResponseCacher` with a `.cache` `Behavior`.
  62 + public static let cache = ResponseCacher(behavior: .cache)
  63 + /// Returns a `ResponseCacher` with a `.doNotCache` `Behavior`.
  64 + public static let doNotCache = ResponseCacher(behavior: .doNotCache)
  65 +
  66 + /// The `Behavior` of the `ResponseCacher`.
  67 + public let behavior: Behavior
  68 +
  69 + /// Creates a `ResponseCacher` instance from the `Behavior`.
  70 + ///
  71 + /// - Parameter behavior: The `Behavior`.
  72 + public init(behavior: Behavior) {
  73 + self.behavior = behavior
  74 + }
  75 +}
  76 +
  77 +extension ResponseCacher: CachedResponseHandler {
  78 + public func dataTask(_ task: URLSessionDataTask,
  79 + willCacheResponse response: CachedURLResponse,
  80 + completion: @escaping (CachedURLResponse?) -> Void) {
  81 + switch behavior {
  82 + case .cache:
  83 + completion(response)
  84 + case .doNotCache:
  85 + completion(nil)
  86 + case let .modify(closure):
  87 + let response = closure(task, response)
  88 + completion(response)
  89 + }
  90 + }
  91 +}
  92 +
  93 +extension CachedResponseHandler where Self == ResponseCacher {
  94 + /// Provides a `ResponseCacher` which caches the response, if allowed. Equivalent to `ResponseCacher.cache`.
  95 + public static var cache: ResponseCacher { .cache }
  96 +
  97 + /// Provides a `ResponseCacher` which does not cache the response. Equivalent to `ResponseCacher.doNotCache`.
  98 + public static var doNotCache: ResponseCacher { .doNotCache }
  99 +
  100 + /// Creates a `ResponseCacher` which modifies the proposed `CachedURLResponse` using the provided closure.
  101 + ///
  102 + /// - Parameter closure: Closure used to modify the `CachedURLResponse`.
  103 + /// - Returns: The `ResponseCacher`.
  104 + public static func modify(using closure: @escaping ((URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)) -> ResponseCacher {
  105 + ResponseCacher(behavior: .modify(closure))
  106 + }
  107 +}
Pods/Alamofire/Source/Combine.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/Combine.swift
  1 +//
  2 +// Combine.swift
  3 +//
  4 +// Copyright (c) 2020 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux))
  26 +
  27 +import Combine
  28 +import Dispatch
  29 +import Foundation
  30 +
  31 +// MARK: - DataRequest / UploadRequest
  32 +
  33 +/// A Combine `Publisher` that publishes the `DataResponse<Value, AFError>` of the provided `DataRequest`.
  34 +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  35 +public struct DataResponsePublisher<Value>: Publisher {
  36 + public typealias Output = DataResponse<Value, AFError>
  37 + public typealias Failure = Never
  38 +
  39 + private typealias Handler = (@escaping (_ response: DataResponse<Value, AFError>) -> Void) -> DataRequest
  40 +
  41 + private let request: DataRequest
  42 + private let responseHandler: Handler
  43 +
  44 + /// Creates an instance which will serialize responses using the provided `ResponseSerializer`.
  45 + ///
  46 + /// - Parameters:
  47 + /// - request: `DataRequest` for which to publish the response.
  48 + /// - queue: `DispatchQueue` on which the `DataResponse` value will be published. `.main` by default.
  49 + /// - serializer: `ResponseSerializer` used to produce the published `DataResponse`.
  50 + public init<Serializer: ResponseSerializer>(_ request: DataRequest, queue: DispatchQueue, serializer: Serializer)
  51 + where Value == Serializer.SerializedObject {
  52 + self.request = request
  53 + responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
  54 + }
  55 +
  56 + /// Creates an instance which will serialize responses using the provided `DataResponseSerializerProtocol`.
  57 + ///
  58 + /// - Parameters:
  59 + /// - request: `DataRequest` for which to publish the response.
  60 + /// - queue: `DispatchQueue` on which the `DataResponse` value will be published. `.main` by default.
  61 + /// - serializer: `DataResponseSerializerProtocol` used to produce the published `DataResponse`.
  62 + public init<Serializer: DataResponseSerializerProtocol>(_ request: DataRequest,
  63 + queue: DispatchQueue,
  64 + serializer: Serializer)
  65 + where Value == Serializer.SerializedObject {
  66 + self.request = request
  67 + responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
  68 + }
  69 +
  70 + /// Publishes only the `Result` of the `DataResponse` value.
  71 + ///
  72 + /// - Returns: The `AnyPublisher` publishing the `Result<Value, AFError>` value.
  73 + public func result() -> AnyPublisher<Result<Value, AFError>, Never> {
  74 + map(\.result).eraseToAnyPublisher()
  75 + }
  76 +
  77 + /// Publishes the `Result` of the `DataResponse` as a single `Value` or fail with the `AFError` instance.
  78 + ///
  79 + /// - Returns: The `AnyPublisher<Value, AFError>` publishing the stream.
  80 + public func value() -> AnyPublisher<Value, AFError> {
  81 + setFailureType(to: AFError.self).flatMap(\.result.publisher).eraseToAnyPublisher()
  82 + }
  83 +
  84 + public func receive<S>(subscriber: S) where S: Subscriber, DataResponsePublisher.Failure == S.Failure, DataResponsePublisher.Output == S.Input {
  85 + subscriber.receive(subscription: Inner(request: request,
  86 + responseHandler: responseHandler,
  87 + downstream: subscriber))
  88 + }
  89 +
  90 + private final class Inner<Downstream: Subscriber>: Subscription
  91 + where Downstream.Input == Output {
  92 + typealias Failure = Downstream.Failure
  93 +
  94 + @Protected
  95 + private var downstream: Downstream?
  96 + private let request: DataRequest
  97 + private let responseHandler: Handler
  98 +
  99 + init(request: DataRequest, responseHandler: @escaping Handler, downstream: Downstream) {
  100 + self.request = request
  101 + self.responseHandler = responseHandler
  102 + self.downstream = downstream
  103 + }
  104 +
  105 + func request(_ demand: Subscribers.Demand) {
  106 + assert(demand > 0)
  107 +
  108 + guard let downstream = downstream else { return }
  109 +
  110 + self.downstream = nil
  111 + responseHandler { response in
  112 + _ = downstream.receive(response)
  113 + downstream.receive(completion: .finished)
  114 + }.resume()
  115 + }
  116 +
  117 + func cancel() {
  118 + request.cancel()
  119 + downstream = nil
  120 + }
  121 + }
  122 +}
  123 +
  124 +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  125 +extension DataResponsePublisher where Value == Data? {
  126 + /// Creates an instance which publishes a `DataResponse<Data?, AFError>` value without serialization.
  127 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  128 + public init(_ request: DataRequest, queue: DispatchQueue) {
  129 + self.request = request
  130 + responseHandler = { request.response(queue: queue, completionHandler: $0) }
  131 + }
  132 +}
  133 +
  134 +extension DataRequest {
  135 + /// Creates a `DataResponsePublisher` for this instance using the given `ResponseSerializer` and `DispatchQueue`.
  136 + ///
  137 + /// - Parameters:
  138 + /// - serializer: `ResponseSerializer` used to serialize response `Data`.
  139 + /// - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
  140 + ///
  141 + /// - Returns: The `DataResponsePublisher`.
  142 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  143 + public func publishResponse<Serializer: ResponseSerializer, T>(using serializer: Serializer, on queue: DispatchQueue = .main) -> DataResponsePublisher<T>
  144 + where Serializer.SerializedObject == T {
  145 + DataResponsePublisher(self, queue: queue, serializer: serializer)
  146 + }
  147 +
  148 + /// Creates a `DataResponsePublisher` for this instance and uses a `DataResponseSerializer` to serialize the
  149 + /// response.
  150 + ///
  151 + /// - Parameters:
  152 + /// - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
  153 + /// - preprocessor: `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
  154 + /// by default.
  155 + /// - emptyResponseCodes: `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
  156 + /// default.
  157 + /// - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
  158 + /// status code. `[.head]` by default.
  159 + /// - Returns: The `DataResponsePublisher`.
  160 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  161 + public func publishData(queue: DispatchQueue = .main,
  162 + preprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
  163 + emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
  164 + emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DataResponsePublisher<Data> {
  165 + publishResponse(using: DataResponseSerializer(dataPreprocessor: preprocessor,
  166 + emptyResponseCodes: emptyResponseCodes,
  167 + emptyRequestMethods: emptyRequestMethods),
  168 + on: queue)
  169 + }
  170 +
  171 + /// Creates a `DataResponsePublisher` for this instance and uses a `StringResponseSerializer` to serialize the
  172 + /// response.
  173 + ///
  174 + /// - Parameters:
  175 + /// - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
  176 + /// - preprocessor: `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
  177 + /// by default.
  178 + /// - encoding: `String.Encoding` to parse the response. `nil` by default, in which case the encoding
  179 + /// will be determined by the server response, falling back to the default HTTP character
  180 + /// set, `ISO-8859-1`.
  181 + /// - emptyResponseCodes: `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
  182 + /// default.
  183 + /// - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
  184 + /// status code. `[.head]` by default.
  185 + ///
  186 + /// - Returns: The `DataResponsePublisher`.
  187 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  188 + public func publishString(queue: DispatchQueue = .main,
  189 + preprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
  190 + encoding: String.Encoding? = nil,
  191 + emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
  192 + emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DataResponsePublisher<String> {
  193 + publishResponse(using: StringResponseSerializer(dataPreprocessor: preprocessor,
  194 + encoding: encoding,
  195 + emptyResponseCodes: emptyResponseCodes,
  196 + emptyRequestMethods: emptyRequestMethods),
  197 + on: queue)
  198 + }
  199 +
  200 + @_disfavoredOverload
  201 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  202 + @available(*, deprecated, message: "Renamed publishDecodable(type:queue:preprocessor:decoder:emptyResponseCodes:emptyRequestMethods).")
  203 + public func publishDecodable<T: Decodable>(type: T.Type = T.self,
  204 + queue: DispatchQueue = .main,
  205 + preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
  206 + decoder: DataDecoder = JSONDecoder(),
  207 + emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
  208 + emptyResponseMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DataResponsePublisher<T> {
  209 + publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
  210 + decoder: decoder,
  211 + emptyResponseCodes: emptyResponseCodes,
  212 + emptyRequestMethods: emptyResponseMethods),
  213 + on: queue)
  214 + }
  215 +
  216 + /// Creates a `DataResponsePublisher` for this instance and uses a `DecodableResponseSerializer` to serialize the
  217 + /// response.
  218 + ///
  219 + /// - Parameters:
  220 + /// - type: `Decodable` type to which to decode response `Data`. Inferred from the context by
  221 + /// default.
  222 + /// - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
  223 + /// - preprocessor: `DataPreprocessor` which filters the `Data` before serialization.
  224 + /// `PassthroughPreprocessor()` by default.
  225 + /// - decoder: `DataDecoder` instance used to decode response `Data`. `JSONDecoder()` by default.
  226 + /// - emptyResponseCodes: `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
  227 + /// default.
  228 + /// - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
  229 + /// status code. `[.head]` by default.
  230 + ///
  231 + /// - Returns: The `DataResponsePublisher`.
  232 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  233 + public func publishDecodable<T: Decodable>(type: T.Type = T.self,
  234 + queue: DispatchQueue = .main,
  235 + preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
  236 + decoder: DataDecoder = JSONDecoder(),
  237 + emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
  238 + emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DataResponsePublisher<T> {
  239 + publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
  240 + decoder: decoder,
  241 + emptyResponseCodes: emptyResponseCodes,
  242 + emptyRequestMethods: emptyRequestMethods),
  243 + on: queue)
  244 + }
  245 +
  246 + /// Creates a `DataResponsePublisher` for this instance which does not serialize the response before publishing.
  247 + ///
  248 + /// - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
  249 + ///
  250 + /// - Returns: The `DataResponsePublisher`.
  251 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  252 + public func publishUnserialized(queue: DispatchQueue = .main) -> DataResponsePublisher<Data?> {
  253 + DataResponsePublisher(self, queue: queue)
  254 + }
  255 +}
  256 +
  257 +// A Combine `Publisher` that publishes a sequence of `Stream<Value, AFError>` values received by the provided `DataStreamRequest`.
  258 +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  259 +public struct DataStreamPublisher<Value>: Publisher {
  260 + public typealias Output = DataStreamRequest.Stream<Value, AFError>
  261 + public typealias Failure = Never
  262 +
  263 + private typealias Handler = (@escaping DataStreamRequest.Handler<Value, AFError>) -> DataStreamRequest
  264 +
  265 + private let request: DataStreamRequest
  266 + private let streamHandler: Handler
  267 +
  268 + /// Creates an instance which will serialize responses using the provided `DataStreamSerializer`.
  269 + ///
  270 + /// - Parameters:
  271 + /// - request: `DataStreamRequest` for which to publish the response.
  272 + /// - queue: `DispatchQueue` on which the `Stream<Value, AFError>` values will be published. `.main` by
  273 + /// default.
  274 + /// - serializer: `DataStreamSerializer` used to produce the published `Stream<Value, AFError>` values.
  275 + public init<Serializer: DataStreamSerializer>(_ request: DataStreamRequest, queue: DispatchQueue, serializer: Serializer)
  276 + where Value == Serializer.SerializedObject {
  277 + self.request = request
  278 + streamHandler = { request.responseStream(using: serializer, on: queue, stream: $0) }
  279 + }
  280 +
  281 + /// Publishes only the `Result` of the `DataStreamRequest.Stream`'s `Event`s.
  282 + ///
  283 + /// - Returns: The `AnyPublisher` publishing the `Result<Value, AFError>` value.
  284 + public func result() -> AnyPublisher<Result<Value, AFError>, Never> {
  285 + compactMap { stream in
  286 + switch stream.event {
  287 + case let .stream(result):
  288 + return result
  289 + // If the stream has completed with an error, send the error value downstream as a `.failure`.
  290 + case let .complete(completion):
  291 + return completion.error.map(Result.failure)
  292 + }
  293 + }
  294 + .eraseToAnyPublisher()
  295 + }
  296 +
  297 + /// Publishes the streamed values of the `DataStreamRequest.Stream` as a sequence of `Value` or fail with the
  298 + /// `AFError` instance.
  299 + ///
  300 + /// - Returns: The `AnyPublisher<Value, AFError>` publishing the stream.
  301 + public func value() -> AnyPublisher<Value, AFError> {
  302 + result().setFailureType(to: AFError.self).flatMap(\.publisher).eraseToAnyPublisher()
  303 + }
  304 +
  305 + public func receive<S>(subscriber: S) where S: Subscriber, DataStreamPublisher.Failure == S.Failure, DataStreamPublisher.Output == S.Input {
  306 + subscriber.receive(subscription: Inner(request: request,
  307 + streamHandler: streamHandler,
  308 + downstream: subscriber))
  309 + }
  310 +
  311 + private final class Inner<Downstream: Subscriber>: Subscription
  312 + where Downstream.Input == Output {
  313 + typealias Failure = Downstream.Failure
  314 +
  315 + @Protected
  316 + private var downstream: Downstream?
  317 + private let request: DataStreamRequest
  318 + private let streamHandler: Handler
  319 +
  320 + init(request: DataStreamRequest, streamHandler: @escaping Handler, downstream: Downstream) {
  321 + self.request = request
  322 + self.streamHandler = streamHandler
  323 + self.downstream = downstream
  324 + }
  325 +
  326 + func request(_ demand: Subscribers.Demand) {
  327 + assert(demand > 0)
  328 +
  329 + guard let downstream = downstream else { return }
  330 +
  331 + self.downstream = nil
  332 + streamHandler { stream in
  333 + _ = downstream.receive(stream)
  334 + if case .complete = stream.event {
  335 + downstream.receive(completion: .finished)
  336 + }
  337 + }.resume()
  338 + }
  339 +
  340 + func cancel() {
  341 + request.cancel()
  342 + downstream = nil
  343 + }
  344 + }
  345 +}
  346 +
  347 +extension DataStreamRequest {
  348 + /// Creates a `DataStreamPublisher` for this instance using the given `DataStreamSerializer` and `DispatchQueue`.
  349 + ///
  350 + /// - Parameters:
  351 + /// - serializer: `DataStreamSerializer` used to serialize the streamed `Data`.
  352 + /// - queue: `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
  353 + /// - Returns: The `DataStreamPublisher`.
  354 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  355 + public func publishStream<Serializer: DataStreamSerializer>(using serializer: Serializer,
  356 + on queue: DispatchQueue = .main) -> DataStreamPublisher<Serializer.SerializedObject> {
  357 + DataStreamPublisher(self, queue: queue, serializer: serializer)
  358 + }
  359 +
  360 + /// Creates a `DataStreamPublisher` for this instance which uses a `PassthroughStreamSerializer` to stream `Data`
  361 + /// unserialized.
  362 + ///
  363 + /// - Parameters:
  364 + /// - queue: `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
  365 + /// - Returns: The `DataStreamPublisher`.
  366 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  367 + public func publishData(queue: DispatchQueue = .main) -> DataStreamPublisher<Data> {
  368 + publishStream(using: PassthroughStreamSerializer(), on: queue)
  369 + }
  370 +
  371 + /// Creates a `DataStreamPublisher` for this instance which uses a `StringStreamSerializer` to serialize stream
  372 + /// `Data` values into `String` values.
  373 + ///
  374 + /// - Parameters:
  375 + /// - queue: `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
  376 + /// - Returns: The `DataStreamPublisher`.
  377 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  378 + public func publishString(queue: DispatchQueue = .main) -> DataStreamPublisher<String> {
  379 + publishStream(using: StringStreamSerializer(), on: queue)
  380 + }
  381 +
  382 + /// Creates a `DataStreamPublisher` for this instance which uses a `DecodableStreamSerializer` with the provided
  383 + /// parameters to serialize stream `Data` values into the provided type.
  384 + ///
  385 + /// - Parameters:
  386 + /// - type: `Decodable` type to which to decode stream `Data`. Inferred from the context by default.
  387 + /// - queue: `DispatchQueue` on which the `DataRequest.Stream` values will be published. `.main` by default.
  388 + /// - decoder: `DataDecoder` instance used to decode stream `Data`. `JSONDecoder()` by default.
  389 + /// - preprocessor: `DataPreprocessor` which filters incoming stream `Data` before serialization.
  390 + /// `PassthroughPreprocessor()` by default.
  391 + /// - Returns: The `DataStreamPublisher`.
  392 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  393 + public func publishDecodable<T: Decodable>(type: T.Type = T.self,
  394 + queue: DispatchQueue = .main,
  395 + decoder: DataDecoder = JSONDecoder(),
  396 + preprocessor: DataPreprocessor = PassthroughPreprocessor()) -> DataStreamPublisher<T> {
  397 + publishStream(using: DecodableStreamSerializer(decoder: decoder,
  398 + dataPreprocessor: preprocessor),
  399 + on: queue)
  400 + }
  401 +}
  402 +
  403 +/// A Combine `Publisher` that publishes the `DownloadResponse<Value, AFError>` of the provided `DownloadRequest`.
  404 +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  405 +public struct DownloadResponsePublisher<Value>: Publisher {
  406 + public typealias Output = DownloadResponse<Value, AFError>
  407 + public typealias Failure = Never
  408 +
  409 + private typealias Handler = (@escaping (_ response: DownloadResponse<Value, AFError>) -> Void) -> DownloadRequest
  410 +
  411 + private let request: DownloadRequest
  412 + private let responseHandler: Handler
  413 +
  414 + /// Creates an instance which will serialize responses using the provided `ResponseSerializer`.
  415 + ///
  416 + /// - Parameters:
  417 + /// - request: `DownloadRequest` for which to publish the response.
  418 + /// - queue: `DispatchQueue` on which the `DownloadResponse` value will be published. `.main` by default.
  419 + /// - serializer: `ResponseSerializer` used to produce the published `DownloadResponse`.
  420 + public init<Serializer: ResponseSerializer>(_ request: DownloadRequest, queue: DispatchQueue, serializer: Serializer)
  421 + where Value == Serializer.SerializedObject {
  422 + self.request = request
  423 + responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
  424 + }
  425 +
  426 + /// Creates an instance which will serialize responses using the provided `DownloadResponseSerializerProtocol` value.
  427 + ///
  428 + /// - Parameters:
  429 + /// - request: `DownloadRequest` for which to publish the response.
  430 + /// - queue: `DispatchQueue` on which the `DataResponse` value will be published. `.main` by default.
  431 + /// - serializer: `DownloadResponseSerializerProtocol` used to produce the published `DownloadResponse`.
  432 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  433 + public init<Serializer: DownloadResponseSerializerProtocol>(_ request: DownloadRequest,
  434 + queue: DispatchQueue,
  435 + serializer: Serializer)
  436 + where Value == Serializer.SerializedObject {
  437 + self.request = request
  438 + responseHandler = { request.response(queue: queue, responseSerializer: serializer, completionHandler: $0) }
  439 + }
  440 +
  441 + /// Publishes only the `Result` of the `DownloadResponse` value.
  442 + ///
  443 + /// - Returns: The `AnyPublisher` publishing the `Result<Value, AFError>` value.
  444 + public func result() -> AnyPublisher<Result<Value, AFError>, Never> {
  445 + map(\.result).eraseToAnyPublisher()
  446 + }
  447 +
  448 + /// Publishes the `Result` of the `DownloadResponse` as a single `Value` or fail with the `AFError` instance.
  449 + ///
  450 + /// - Returns: The `AnyPublisher<Value, AFError>` publishing the stream.
  451 + public func value() -> AnyPublisher<Value, AFError> {
  452 + setFailureType(to: AFError.self).flatMap(\.result.publisher).eraseToAnyPublisher()
  453 + }
  454 +
  455 + public func receive<S>(subscriber: S) where S: Subscriber, DownloadResponsePublisher.Failure == S.Failure, DownloadResponsePublisher.Output == S.Input {
  456 + subscriber.receive(subscription: Inner(request: request,
  457 + responseHandler: responseHandler,
  458 + downstream: subscriber))
  459 + }
  460 +
  461 + private final class Inner<Downstream: Subscriber>: Subscription
  462 + where Downstream.Input == Output {
  463 + typealias Failure = Downstream.Failure
  464 +
  465 + @Protected
  466 + private var downstream: Downstream?
  467 + private let request: DownloadRequest
  468 + private let responseHandler: Handler
  469 +
  470 + init(request: DownloadRequest, responseHandler: @escaping Handler, downstream: Downstream) {
  471 + self.request = request
  472 + self.responseHandler = responseHandler
  473 + self.downstream = downstream
  474 + }
  475 +
  476 + func request(_ demand: Subscribers.Demand) {
  477 + assert(demand > 0)
  478 +
  479 + guard let downstream = downstream else { return }
  480 +
  481 + self.downstream = nil
  482 + responseHandler { response in
  483 + _ = downstream.receive(response)
  484 + downstream.receive(completion: .finished)
  485 + }.resume()
  486 + }
  487 +
  488 + func cancel() {
  489 + request.cancel()
  490 + downstream = nil
  491 + }
  492 + }
  493 +}
  494 +
  495 +extension DownloadRequest {
  496 + /// Creates a `DownloadResponsePublisher` for this instance using the given `ResponseSerializer` and `DispatchQueue`.
  497 + ///
  498 + /// - Parameters:
  499 + /// - serializer: `ResponseSerializer` used to serialize the response `Data` from disk.
  500 + /// - queue: `DispatchQueue` on which the `DownloadResponse` will be published.`.main` by default.
  501 + ///
  502 + /// - Returns: The `DownloadResponsePublisher`.
  503 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  504 + public func publishResponse<Serializer: ResponseSerializer, T>(using serializer: Serializer, on queue: DispatchQueue = .main) -> DownloadResponsePublisher<T>
  505 + where Serializer.SerializedObject == T {
  506 + DownloadResponsePublisher(self, queue: queue, serializer: serializer)
  507 + }
  508 +
  509 + /// Creates a `DownloadResponsePublisher` for this instance using the given `DownloadResponseSerializerProtocol` and
  510 + /// `DispatchQueue`.
  511 + ///
  512 + /// - Parameters:
  513 + /// - serializer: `DownloadResponseSerializer` used to serialize the response `Data` from disk.
  514 + /// - queue: `DispatchQueue` on which the `DownloadResponse` will be published.`.main` by default.
  515 + ///
  516 + /// - Returns: The `DownloadResponsePublisher`.
  517 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  518 + public func publishResponse<Serializer: DownloadResponseSerializerProtocol, T>(using serializer: Serializer, on queue: DispatchQueue = .main) -> DownloadResponsePublisher<T>
  519 + where Serializer.SerializedObject == T {
  520 + DownloadResponsePublisher(self, queue: queue, serializer: serializer)
  521 + }
  522 +
  523 + /// Creates a `DownloadResponsePublisher` for this instance and uses a `URLResponseSerializer` to serialize the
  524 + /// response.
  525 + ///
  526 + /// - Parameter queue: `DispatchQueue` on which the `DownloadResponse` will be published. `.main` by default.
  527 + ///
  528 + /// - Returns: The `DownloadResponsePublisher`.
  529 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  530 + public func publishURL(queue: DispatchQueue = .main) -> DownloadResponsePublisher<URL> {
  531 + publishResponse(using: URLResponseSerializer(), on: queue)
  532 + }
  533 +
  534 + /// Creates a `DownloadResponsePublisher` for this instance and uses a `DataResponseSerializer` to serialize the
  535 + /// response.
  536 + ///
  537 + /// - Parameters:
  538 + /// - queue: `DispatchQueue` on which the `DownloadResponse` will be published. `.main` by default.
  539 + /// - preprocessor: `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
  540 + /// by default.
  541 + /// - emptyResponseCodes: `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
  542 + /// default.
  543 + /// - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
  544 + /// status code. `[.head]` by default.
  545 + ///
  546 + /// - Returns: The `DownloadResponsePublisher`.
  547 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  548 + public func publishData(queue: DispatchQueue = .main,
  549 + preprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
  550 + emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
  551 + emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DownloadResponsePublisher<Data> {
  552 + publishResponse(using: DataResponseSerializer(dataPreprocessor: preprocessor,
  553 + emptyResponseCodes: emptyResponseCodes,
  554 + emptyRequestMethods: emptyRequestMethods),
  555 + on: queue)
  556 + }
  557 +
  558 + /// Creates a `DownloadResponsePublisher` for this instance and uses a `StringResponseSerializer` to serialize the
  559 + /// response.
  560 + ///
  561 + /// - Parameters:
  562 + /// - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
  563 + /// - preprocessor: `DataPreprocessor` which filters the `Data` before serialization. `PassthroughPreprocessor()`
  564 + /// by default.
  565 + /// - encoding: `String.Encoding` to parse the response. `nil` by default, in which case the encoding
  566 + /// will be determined by the server response, falling back to the default HTTP character
  567 + /// set, `ISO-8859-1`.
  568 + /// - emptyResponseCodes: `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
  569 + /// default.
  570 + /// - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless of
  571 + /// status code. `[.head]` by default.
  572 + ///
  573 + /// - Returns: The `DownloadResponsePublisher`.
  574 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  575 + public func publishString(queue: DispatchQueue = .main,
  576 + preprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
  577 + encoding: String.Encoding? = nil,
  578 + emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
  579 + emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DownloadResponsePublisher<String> {
  580 + publishResponse(using: StringResponseSerializer(dataPreprocessor: preprocessor,
  581 + encoding: encoding,
  582 + emptyResponseCodes: emptyResponseCodes,
  583 + emptyRequestMethods: emptyRequestMethods),
  584 + on: queue)
  585 + }
  586 +
  587 + @_disfavoredOverload
  588 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  589 + @available(*, deprecated, message: "Renamed publishDecodable(type:queue:preprocessor:decoder:emptyResponseCodes:emptyRequestMethods).")
  590 + public func publishDecodable<T: Decodable>(type: T.Type = T.self,
  591 + queue: DispatchQueue = .main,
  592 + preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
  593 + decoder: DataDecoder = JSONDecoder(),
  594 + emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
  595 + emptyResponseMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DownloadResponsePublisher<T> {
  596 + publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
  597 + decoder: decoder,
  598 + emptyResponseCodes: emptyResponseCodes,
  599 + emptyRequestMethods: emptyResponseMethods),
  600 + on: queue)
  601 + }
  602 +
  603 + /// Creates a `DownloadResponsePublisher` for this instance and uses a `DecodableResponseSerializer` to serialize
  604 + /// the response.
  605 + ///
  606 + /// - Parameters:
  607 + /// - type: `Decodable` type to which to decode response `Data`. Inferred from the context by default.
  608 + /// - queue: `DispatchQueue` on which the `DataResponse` will be published. `.main` by default.
  609 + /// - preprocessor: `DataPreprocessor` which filters the `Data` before serialization.
  610 + /// `PassthroughPreprocessor()` by default.
  611 + /// - decoder: `DataDecoder` instance used to decode response `Data`. `JSONDecoder()` by default.
  612 + /// - emptyResponseCodes: `Set<Int>` of HTTP status codes for which empty responses are allowed. `[204, 205]` by
  613 + /// default.
  614 + /// - emptyRequestMethods: `Set<HTTPMethod>` of `HTTPMethod`s for which empty responses are allowed, regardless
  615 + /// of status code. `[.head]` by default.
  616 + ///
  617 + /// - Returns: The `DownloadResponsePublisher`.
  618 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  619 + public func publishDecodable<T: Decodable>(type: T.Type = T.self,
  620 + queue: DispatchQueue = .main,
  621 + preprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
  622 + decoder: DataDecoder = JSONDecoder(),
  623 + emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
  624 + emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DownloadResponsePublisher<T> {
  625 + publishResponse(using: DecodableResponseSerializer(dataPreprocessor: preprocessor,
  626 + decoder: decoder,
  627 + emptyResponseCodes: emptyResponseCodes,
  628 + emptyRequestMethods: emptyRequestMethods),
  629 + on: queue)
  630 + }
  631 +}
  632 +
  633 +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  634 +extension DownloadResponsePublisher where Value == URL? {
  635 + /// Creates an instance which publishes a `DownloadResponse<URL?, AFError>` value without serialization.
  636 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  637 + public init(_ request: DownloadRequest, queue: DispatchQueue) {
  638 + self.request = request
  639 + responseHandler = { request.response(queue: queue, completionHandler: $0) }
  640 + }
  641 +}
  642 +
  643 +extension DownloadRequest {
  644 + /// Creates a `DownloadResponsePublisher` for this instance which does not serialize the response before publishing.
  645 + ///
  646 + /// - Parameter queue: `DispatchQueue` on which the `DownloadResponse` will be published. `.main` by default.
  647 + ///
  648 + /// - Returns: The `DownloadResponsePublisher`.
  649 + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
  650 + public func publishUnserialized(on queue: DispatchQueue = .main) -> DownloadResponsePublisher<URL?> {
  651 + DownloadResponsePublisher(self, queue: queue)
  652 + }
  653 +}
  654 +
  655 +#endif
Pods/Alamofire/Source/Concurrency.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/Concurrency.swift
  1 +//
  2 +// Concurrency.swift
  3 +//
  4 +// Copyright (c) 2021 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +#if compiler(>=5.6.0) && canImport(_Concurrency)
  26 +
  27 +import Foundation
  28 +
  29 +// MARK: - Request Event Streams
  30 +
  31 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  32 +extension Request {
  33 + /// Creates a `StreamOf<Progress>` for the instance's upload progress.
  34 + ///
  35 + /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  36 + ///
  37 + /// - Returns: The `StreamOf<Progress>`.
  38 + public func uploadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
  39 + stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  40 + uploadProgress(queue: .singleEventQueue) { progress in
  41 + continuation.yield(progress)
  42 + }
  43 + }
  44 + }
  45 +
  46 + /// Creates a `StreamOf<Progress>` for the instance's download progress.
  47 + ///
  48 + /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  49 + ///
  50 + /// - Returns: The `StreamOf<Progress>`.
  51 + public func downloadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
  52 + stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  53 + downloadProgress(queue: .singleEventQueue) { progress in
  54 + continuation.yield(progress)
  55 + }
  56 + }
  57 + }
  58 +
  59 + /// Creates a `StreamOf<URLRequest>` for the `URLRequest`s produced for the instance.
  60 + ///
  61 + /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  62 + ///
  63 + /// - Returns: The `StreamOf<URLRequest>`.
  64 + public func urlRequests(bufferingPolicy: StreamOf<URLRequest>.BufferingPolicy = .unbounded) -> StreamOf<URLRequest> {
  65 + stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  66 + onURLRequestCreation(on: .singleEventQueue) { request in
  67 + continuation.yield(request)
  68 + }
  69 + }
  70 + }
  71 +
  72 + /// Creates a `StreamOf<URLSessionTask>` for the `URLSessionTask`s produced for the instance.
  73 + ///
  74 + /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  75 + ///
  76 + /// - Returns: The `StreamOf<URLSessionTask>`.
  77 + public func urlSessionTasks(bufferingPolicy: StreamOf<URLSessionTask>.BufferingPolicy = .unbounded) -> StreamOf<URLSessionTask> {
  78 + stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  79 + onURLSessionTaskCreation(on: .singleEventQueue) { task in
  80 + continuation.yield(task)
  81 + }
  82 + }
  83 + }
  84 +
  85 + /// Creates a `StreamOf<String>` for the cURL descriptions produced for the instance.
  86 + ///
  87 + /// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  88 + ///
  89 + /// - Returns: The `StreamOf<String>`.
  90 + public func cURLDescriptions(bufferingPolicy: StreamOf<String>.BufferingPolicy = .unbounded) -> StreamOf<String> {
  91 + stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  92 + cURLDescription(on: .singleEventQueue) { description in
  93 + continuation.yield(description)
  94 + }
  95 + }
  96 + }
  97 +
  98 + private func stream<T>(of type: T.Type = T.self,
  99 + bufferingPolicy: StreamOf<T>.BufferingPolicy = .unbounded,
  100 + yielder: @escaping (StreamOf<T>.Continuation) -> Void) -> StreamOf<T> {
  101 + StreamOf<T>(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
  102 + yielder(continuation)
  103 + // Must come after serializers run in order to catch retry progress.
  104 + onFinish {
  105 + continuation.finish()
  106 + }
  107 + }
  108 + }
  109 +}
  110 +
  111 +// MARK: - DataTask
  112 +
  113 +/// Value used to `await` a `DataResponse` and associated values.
  114 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  115 +public struct DataTask<Value> {
  116 + /// `DataResponse` produced by the `DataRequest` and its response handler.
  117 + public var response: DataResponse<Value, AFError> {
  118 + get async {
  119 + if shouldAutomaticallyCancel {
  120 + return await withTaskCancellationHandler {
  121 + await task.value
  122 + } onCancel: {
  123 + cancel()
  124 + }
  125 + } else {
  126 + return await task.value
  127 + }
  128 + }
  129 + }
  130 +
  131 + /// `Result` of any response serialization performed for the `response`.
  132 + public var result: Result<Value, AFError> {
  133 + get async { await response.result }
  134 + }
  135 +
  136 + /// `Value` returned by the `response`.
  137 + public var value: Value {
  138 + get async throws {
  139 + try await result.get()
  140 + }
  141 + }
  142 +
  143 + private let request: DataRequest
  144 + private let task: Task<DataResponse<Value, AFError>, Never>
  145 + private let shouldAutomaticallyCancel: Bool
  146 +
  147 + fileprivate init(request: DataRequest, task: Task<DataResponse<Value, AFError>, Never>, shouldAutomaticallyCancel: Bool) {
  148 + self.request = request
  149 + self.task = task
  150 + self.shouldAutomaticallyCancel = shouldAutomaticallyCancel
  151 + }
  152 +
  153 + /// Cancel the underlying `DataRequest` and `Task`.
  154 + public func cancel() {
  155 + task.cancel()
  156 + }
  157 +
  158 + /// Resume the underlying `DataRequest`.
  159 + public func resume() {
  160 + request.resume()
  161 + }
  162 +
  163 + /// Suspend the underlying `DataRequest`.
  164 + public func suspend() {
  165 + request.suspend()
  166 + }
  167 +}
  168 +
  169 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  170 +extension DataRequest {
  171 + /// Creates a `DataTask` to `await` a `Data` value.
  172 + ///
  173 + /// - Parameters:
  174 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  175 + /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  176 + /// properties. `false` by default.
  177 + /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
  178 + /// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
  179 + /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  180 + ///
  181 + /// - Returns: The `DataTask`.
  182 + public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  183 + dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
  184 + emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
  185 + emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DataTask<Data> {
  186 + serializingResponse(using: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
  187 + emptyResponseCodes: emptyResponseCodes,
  188 + emptyRequestMethods: emptyRequestMethods),
  189 + automaticallyCancelling: shouldAutomaticallyCancel)
  190 + }
  191 +
  192 + /// Creates a `DataTask` to `await` serialization of a `Decodable` value.
  193 + ///
  194 + /// - Parameters:
  195 + /// - type: `Decodable` type to decode from response data.
  196 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  197 + /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  198 + /// properties. `false` by default.
  199 + /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
  200 + /// `PassthroughPreprocessor()` by default.
  201 + /// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
  202 + /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  203 + /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  204 + ///
  205 + /// - Returns: The `DataTask`.
  206 + public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
  207 + automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  208 + dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
  209 + decoder: DataDecoder = JSONDecoder(),
  210 + emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
  211 + emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<Value>.defaultEmptyRequestMethods) -> DataTask<Value> {
  212 + serializingResponse(using: DecodableResponseSerializer<Value>(dataPreprocessor: dataPreprocessor,
  213 + decoder: decoder,
  214 + emptyResponseCodes: emptyResponseCodes,
  215 + emptyRequestMethods: emptyRequestMethods),
  216 + automaticallyCancelling: shouldAutomaticallyCancel)
  217 + }
  218 +
  219 + /// Creates a `DataTask` to `await` serialization of a `String` value.
  220 + ///
  221 + /// - Parameters:
  222 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  223 + /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  224 + /// properties. `false` by default.
  225 + /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
  226 + /// `PassthroughPreprocessor()` by default.
  227 + /// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
  228 + /// the encoding will be determined from the server response, falling back to the
  229 + /// default HTTP character set, `ISO-8859-1`.
  230 + /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  231 + /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  232 + ///
  233 + /// - Returns: The `DataTask`.
  234 + public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  235 + dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
  236 + encoding: String.Encoding? = nil,
  237 + emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
  238 + emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DataTask<String> {
  239 + serializingResponse(using: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
  240 + encoding: encoding,
  241 + emptyResponseCodes: emptyResponseCodes,
  242 + emptyRequestMethods: emptyRequestMethods),
  243 + automaticallyCancelling: shouldAutomaticallyCancel)
  244 + }
  245 +
  246 + /// Creates a `DataTask` to `await` serialization using the provided `ResponseSerializer` instance.
  247 + ///
  248 + /// - Parameters:
  249 + /// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
  250 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  251 + /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  252 + /// properties. `false` by default.
  253 + ///
  254 + /// - Returns: The `DataTask`.
  255 + public func serializingResponse<Serializer: ResponseSerializer>(using serializer: Serializer,
  256 + automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  257 + -> DataTask<Serializer.SerializedObject> {
  258 + dataTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  259 + self.response(queue: .singleEventQueue,
  260 + responseSerializer: serializer,
  261 + completionHandler: $0)
  262 + }
  263 + }
  264 +
  265 + /// Creates a `DataTask` to `await` serialization using the provided `DataResponseSerializerProtocol` instance.
  266 + ///
  267 + /// - Parameters:
  268 + /// - serializer: `DataResponseSerializerProtocol` responsible for serializing the request,
  269 + /// response, and data.
  270 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  271 + /// enclosing async context is cancelled. Only applies to `DataTask`'s async
  272 + /// properties. `false` by default.
  273 + ///
  274 + /// - Returns: The `DataTask`.
  275 + public func serializingResponse<Serializer: DataResponseSerializerProtocol>(using serializer: Serializer,
  276 + automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  277 + -> DataTask<Serializer.SerializedObject> {
  278 + dataTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  279 + self.response(queue: .singleEventQueue,
  280 + responseSerializer: serializer,
  281 + completionHandler: $0)
  282 + }
  283 + }
  284 +
  285 + private func dataTask<Value>(automaticallyCancelling shouldAutomaticallyCancel: Bool,
  286 + forResponse onResponse: @escaping (@escaping (DataResponse<Value, AFError>) -> Void) -> Void)
  287 + -> DataTask<Value> {
  288 + let task = Task {
  289 + await withTaskCancellationHandler {
  290 + await withCheckedContinuation { continuation in
  291 + onResponse {
  292 + continuation.resume(returning: $0)
  293 + }
  294 + }
  295 + } onCancel: {
  296 + self.cancel()
  297 + }
  298 + }
  299 +
  300 + return DataTask<Value>(request: self, task: task, shouldAutomaticallyCancel: shouldAutomaticallyCancel)
  301 + }
  302 +}
  303 +
  304 +// MARK: - DownloadTask
  305 +
  306 +/// Value used to `await` a `DownloadResponse` and associated values.
  307 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  308 +public struct DownloadTask<Value> {
  309 + /// `DownloadResponse` produced by the `DownloadRequest` and its response handler.
  310 + public var response: DownloadResponse<Value, AFError> {
  311 + get async {
  312 + if shouldAutomaticallyCancel {
  313 + return await withTaskCancellationHandler {
  314 + await task.value
  315 + } onCancel: {
  316 + cancel()
  317 + }
  318 + } else {
  319 + return await task.value
  320 + }
  321 + }
  322 + }
  323 +
  324 + /// `Result` of any response serialization performed for the `response`.
  325 + public var result: Result<Value, AFError> {
  326 + get async { await response.result }
  327 + }
  328 +
  329 + /// `Value` returned by the `response`.
  330 + public var value: Value {
  331 + get async throws {
  332 + try await result.get()
  333 + }
  334 + }
  335 +
  336 + private let task: Task<AFDownloadResponse<Value>, Never>
  337 + private let request: DownloadRequest
  338 + private let shouldAutomaticallyCancel: Bool
  339 +
  340 + fileprivate init(request: DownloadRequest, task: Task<AFDownloadResponse<Value>, Never>, shouldAutomaticallyCancel: Bool) {
  341 + self.request = request
  342 + self.task = task
  343 + self.shouldAutomaticallyCancel = shouldAutomaticallyCancel
  344 + }
  345 +
  346 + /// Cancel the underlying `DownloadRequest` and `Task`.
  347 + public func cancel() {
  348 + task.cancel()
  349 + }
  350 +
  351 + /// Resume the underlying `DownloadRequest`.
  352 + public func resume() {
  353 + request.resume()
  354 + }
  355 +
  356 + /// Suspend the underlying `DownloadRequest`.
  357 + public func suspend() {
  358 + request.suspend()
  359 + }
  360 +}
  361 +
  362 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  363 +extension DownloadRequest {
  364 + /// Creates a `DownloadTask` to `await` a `Data` value.
  365 + ///
  366 + /// - Parameters:
  367 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  368 + /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  369 + /// properties. `false` by default.
  370 + /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
  371 + /// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
  372 + /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  373 + ///
  374 + /// - Returns: The `DownloadTask`.
  375 + public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  376 + dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
  377 + emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
  378 + emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DownloadTask<Data> {
  379 + serializingDownload(using: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
  380 + emptyResponseCodes: emptyResponseCodes,
  381 + emptyRequestMethods: emptyRequestMethods),
  382 + automaticallyCancelling: shouldAutomaticallyCancel)
  383 + }
  384 +
  385 + /// Creates a `DownloadTask` to `await` serialization of a `Decodable` value.
  386 + ///
  387 + /// - Note: This serializer reads the entire response into memory before parsing.
  388 + ///
  389 + /// - Parameters:
  390 + /// - type: `Decodable` type to decode from response data.
  391 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  392 + /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  393 + /// properties. `false` by default.
  394 + /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
  395 + /// `PassthroughPreprocessor()` by default.
  396 + /// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
  397 + /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  398 + /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  399 + ///
  400 + /// - Returns: The `DownloadTask`.
  401 + public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
  402 + automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  403 + dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
  404 + decoder: DataDecoder = JSONDecoder(),
  405 + emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
  406 + emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<Value>.defaultEmptyRequestMethods) -> DownloadTask<Value> {
  407 + serializingDownload(using: DecodableResponseSerializer<Value>(dataPreprocessor: dataPreprocessor,
  408 + decoder: decoder,
  409 + emptyResponseCodes: emptyResponseCodes,
  410 + emptyRequestMethods: emptyRequestMethods),
  411 + automaticallyCancelling: shouldAutomaticallyCancel)
  412 + }
  413 +
  414 + /// Creates a `DownloadTask` to `await` serialization of the downloaded file's `URL` on disk.
  415 + ///
  416 + /// - Parameters:
  417 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  418 + /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  419 + /// properties. `false` by default.
  420 + ///
  421 + /// - Returns: The `DownloadTask`.
  422 + public func serializingDownloadedFileURL(automaticallyCancelling shouldAutomaticallyCancel: Bool = false) -> DownloadTask<URL> {
  423 + serializingDownload(using: URLResponseSerializer(),
  424 + automaticallyCancelling: shouldAutomaticallyCancel)
  425 + }
  426 +
  427 + /// Creates a `DownloadTask` to `await` serialization of a `String` value.
  428 + ///
  429 + /// - Parameters:
  430 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  431 + /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  432 + /// properties. `false` by default.
  433 + /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
  434 + /// serializer. `PassthroughPreprocessor()` by default.
  435 + /// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
  436 + /// the encoding will be determined from the server response, falling back to the
  437 + /// default HTTP character set, `ISO-8859-1`.
  438 + /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
  439 + /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
  440 + ///
  441 + /// - Returns: The `DownloadTask`.
  442 + public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
  443 + dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
  444 + encoding: String.Encoding? = nil,
  445 + emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
  446 + emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> DownloadTask<String> {
  447 + serializingDownload(using: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
  448 + encoding: encoding,
  449 + emptyResponseCodes: emptyResponseCodes,
  450 + emptyRequestMethods: emptyRequestMethods),
  451 + automaticallyCancelling: shouldAutomaticallyCancel)
  452 + }
  453 +
  454 + /// Creates a `DownloadTask` to `await` serialization using the provided `ResponseSerializer` instance.
  455 + ///
  456 + /// - Parameters:
  457 + /// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
  458 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  459 + /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  460 + /// properties. `false` by default.
  461 + ///
  462 + /// - Returns: The `DownloadTask`.
  463 + public func serializingDownload<Serializer: ResponseSerializer>(using serializer: Serializer,
  464 + automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  465 + -> DownloadTask<Serializer.SerializedObject> {
  466 + downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  467 + self.response(queue: .singleEventQueue,
  468 + responseSerializer: serializer,
  469 + completionHandler: $0)
  470 + }
  471 + }
  472 +
  473 + /// Creates a `DownloadTask` to `await` serialization using the provided `DownloadResponseSerializerProtocol`
  474 + /// instance.
  475 + ///
  476 + /// - Parameters:
  477 + /// - serializer: `DownloadResponseSerializerProtocol` responsible for serializing the request,
  478 + /// response, and data.
  479 + /// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
  480 + /// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
  481 + /// properties. `false` by default.
  482 + ///
  483 + /// - Returns: The `DownloadTask`.
  484 + public func serializingDownload<Serializer: DownloadResponseSerializerProtocol>(using serializer: Serializer,
  485 + automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
  486 + -> DownloadTask<Serializer.SerializedObject> {
  487 + downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) {
  488 + self.response(queue: .singleEventQueue,
  489 + responseSerializer: serializer,
  490 + completionHandler: $0)
  491 + }
  492 + }
  493 +
  494 + private func downloadTask<Value>(automaticallyCancelling shouldAutomaticallyCancel: Bool,
  495 + forResponse onResponse: @escaping (@escaping (DownloadResponse<Value, AFError>) -> Void) -> Void)
  496 + -> DownloadTask<Value> {
  497 + let task = Task {
  498 + await withTaskCancellationHandler {
  499 + await withCheckedContinuation { continuation in
  500 + onResponse {
  501 + continuation.resume(returning: $0)
  502 + }
  503 + }
  504 + } onCancel: {
  505 + self.cancel()
  506 + }
  507 + }
  508 +
  509 + return DownloadTask<Value>(request: self, task: task, shouldAutomaticallyCancel: shouldAutomaticallyCancel)
  510 + }
  511 +}
  512 +
  513 +// MARK: - DataStreamTask
  514 +
  515 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  516 +public struct DataStreamTask {
  517 + // Type of created streams.
  518 + public typealias Stream<Success, Failure: Error> = StreamOf<DataStreamRequest.Stream<Success, Failure>>
  519 +
  520 + private let request: DataStreamRequest
  521 +
  522 + fileprivate init(request: DataStreamRequest) {
  523 + self.request = request
  524 + }
  525 +
  526 + /// Creates a `Stream` of `Data` values from the underlying `DataStreamRequest`.
  527 + ///
  528 + /// - Parameters:
  529 + /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  530 + /// which observation of the stream stops. `true` by default.
  531 + /// - bufferingPolicy: ` BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  532 + ///
  533 + /// - Returns: The `Stream`.
  534 + public func streamingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = true, bufferingPolicy: Stream<Data, Never>.BufferingPolicy = .unbounded) -> Stream<Data, Never> {
  535 + createStream(automaticallyCancelling: shouldAutomaticallyCancel, bufferingPolicy: bufferingPolicy) { onStream in
  536 + request.responseStream(on: .streamCompletionQueue(forRequestID: request.id), stream: onStream)
  537 + }
  538 + }
  539 +
  540 + /// Creates a `Stream` of `UTF-8` `String`s from the underlying `DataStreamRequest`.
  541 + ///
  542 + /// - Parameters:
  543 + /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  544 + /// which observation of the stream stops. `true` by default.
  545 + /// - bufferingPolicy: ` BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  546 + /// - Returns:
  547 + public func streamingStrings(automaticallyCancelling shouldAutomaticallyCancel: Bool = true, bufferingPolicy: Stream<String, Never>.BufferingPolicy = .unbounded) -> Stream<String, Never> {
  548 + createStream(automaticallyCancelling: shouldAutomaticallyCancel, bufferingPolicy: bufferingPolicy) { onStream in
  549 + request.responseStreamString(on: .streamCompletionQueue(forRequestID: request.id), stream: onStream)
  550 + }
  551 + }
  552 +
  553 + /// Creates a `Stream` of `Decodable` values from the underlying `DataStreamRequest`.
  554 + ///
  555 + /// - Parameters:
  556 + /// - type: `Decodable` type to be serialized from stream payloads.
  557 + /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  558 + /// which observation of the stream stops. `true` by default.
  559 + /// - bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  560 + ///
  561 + /// - Returns: The `Stream`.
  562 + public func streamingDecodables<T>(_ type: T.Type = T.self,
  563 + automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
  564 + bufferingPolicy: Stream<T, AFError>.BufferingPolicy = .unbounded)
  565 + -> Stream<T, AFError> where T: Decodable {
  566 + streamingResponses(serializedUsing: DecodableStreamSerializer<T>(),
  567 + automaticallyCancelling: shouldAutomaticallyCancel,
  568 + bufferingPolicy: bufferingPolicy)
  569 + }
  570 +
  571 + /// Creates a `Stream` of values using the provided `DataStreamSerializer` from the underlying `DataStreamRequest`.
  572 + ///
  573 + /// - Parameters:
  574 + /// - serializer: `DataStreamSerializer` to use to serialize incoming `Data`.
  575 + /// - shouldAutomaticallyCancel: `Bool` indicating whether the underlying `DataStreamRequest` should be canceled
  576 + /// which observation of the stream stops. `true` by default.
  577 + /// - bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
  578 + ///
  579 + /// - Returns: The `Stream`.
  580 + public func streamingResponses<Serializer: DataStreamSerializer>(serializedUsing serializer: Serializer,
  581 + automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
  582 + bufferingPolicy: Stream<Serializer.SerializedObject, AFError>.BufferingPolicy = .unbounded)
  583 + -> Stream<Serializer.SerializedObject, AFError> {
  584 + createStream(automaticallyCancelling: shouldAutomaticallyCancel, bufferingPolicy: bufferingPolicy) { onStream in
  585 + request.responseStream(using: serializer,
  586 + on: .streamCompletionQueue(forRequestID: request.id),
  587 + stream: onStream)
  588 + }
  589 + }
  590 +
  591 + private func createStream<Success, Failure: Error>(automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
  592 + bufferingPolicy: Stream<Success, Failure>.BufferingPolicy = .unbounded,
  593 + forResponse onResponse: @escaping (@escaping (DataStreamRequest.Stream<Success, Failure>) -> Void) -> Void)
  594 + -> Stream<Success, Failure> {
  595 + StreamOf(bufferingPolicy: bufferingPolicy) {
  596 + guard shouldAutomaticallyCancel,
  597 + request.isInitialized || request.isResumed || request.isSuspended else { return }
  598 +
  599 + cancel()
  600 + } builder: { continuation in
  601 + onResponse { stream in
  602 + continuation.yield(stream)
  603 + if case .complete = stream.event {
  604 + continuation.finish()
  605 + }
  606 + }
  607 + }
  608 + }
  609 +
  610 + /// Cancel the underlying `DataStreamRequest`.
  611 + public func cancel() {
  612 + request.cancel()
  613 + }
  614 +
  615 + /// Resume the underlying `DataStreamRequest`.
  616 + public func resume() {
  617 + request.resume()
  618 + }
  619 +
  620 + /// Suspend the underlying `DataStreamRequest`.
  621 + public func suspend() {
  622 + request.suspend()
  623 + }
  624 +}
  625 +
  626 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  627 +extension DataStreamRequest {
  628 + /// Creates a `DataStreamTask` used to `await` streams of serialized values.
  629 + ///
  630 + /// - Returns: The `DataStreamTask`.
  631 + public func streamTask() -> DataStreamTask {
  632 + DataStreamTask(request: self)
  633 + }
  634 +}
  635 +
  636 +extension DispatchQueue {
  637 + fileprivate static let singleEventQueue = DispatchQueue(label: "org.alamofire.concurrencySingleEventQueue",
  638 + attributes: .concurrent)
  639 +
  640 + fileprivate static func streamCompletionQueue(forRequestID id: UUID) -> DispatchQueue {
  641 + DispatchQueue(label: "org.alamofire.concurrencyStreamCompletionQueue-\(id)", target: .singleEventQueue)
  642 + }
  643 +}
  644 +
  645 +/// An asynchronous sequence generated from an underlying `AsyncStream`. Only produced by Alamofire.
  646 +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  647 +public struct StreamOf<Element>: AsyncSequence {
  648 + public typealias AsyncIterator = Iterator
  649 + public typealias BufferingPolicy = AsyncStream<Element>.Continuation.BufferingPolicy
  650 + fileprivate typealias Continuation = AsyncStream<Element>.Continuation
  651 +
  652 + private let bufferingPolicy: BufferingPolicy
  653 + private let onTermination: (() -> Void)?
  654 + private let builder: (Continuation) -> Void
  655 +
  656 + fileprivate init(bufferingPolicy: BufferingPolicy = .unbounded,
  657 + onTermination: (() -> Void)? = nil,
  658 + builder: @escaping (Continuation) -> Void) {
  659 + self.bufferingPolicy = bufferingPolicy
  660 + self.onTermination = onTermination
  661 + self.builder = builder
  662 + }
  663 +
  664 + public func makeAsyncIterator() -> Iterator {
  665 + var continuation: AsyncStream<Element>.Continuation?
  666 + let stream = AsyncStream<Element>(bufferingPolicy: bufferingPolicy) { innerContinuation in
  667 + continuation = innerContinuation
  668 + builder(innerContinuation)
  669 + }
  670 +
  671 + return Iterator(iterator: stream.makeAsyncIterator()) {
  672 + continuation?.finish()
  673 + onTermination?()
  674 + }
  675 + }
  676 +
  677 + public struct Iterator: AsyncIteratorProtocol {
  678 + private final class Token {
  679 + private let onDeinit: () -> Void
  680 +
  681 + init(onDeinit: @escaping () -> Void) {
  682 + self.onDeinit = onDeinit
  683 + }
  684 +
  685 + deinit {
  686 + onDeinit()
  687 + }
  688 + }
  689 +
  690 + private var iterator: AsyncStream<Element>.AsyncIterator
  691 + private let token: Token
  692 +
  693 + init(iterator: AsyncStream<Element>.AsyncIterator, onCancellation: @escaping () -> Void) {
  694 + self.iterator = iterator
  695 + token = Token(onDeinit: onCancellation)
  696 + }
  697 +
  698 + public mutating func next() async -> Element? {
  699 + await iterator.next()
  700 + }
  701 + }
  702 +}
  703 +
  704 +#endif
Pods/Alamofire/Source/DispatchQueue+Alamofire.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift
  1 +//
  2 +// DispatchQueue+Alamofire.swift
  3 +//
  4 +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +import Dispatch
  26 +import Foundation
  27 +
  28 +extension DispatchQueue {
  29 + /// Execute the provided closure after a `TimeInterval`.
  30 + ///
  31 + /// - Parameters:
  32 + /// - delay: `TimeInterval` to delay execution.
  33 + /// - closure: Closure to execute.
  34 + func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) {
  35 + asyncAfter(deadline: .now() + delay, execute: closure)
  36 + }
  37 +}
Pods/Alamofire/Source/EventMonitor.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/EventMonitor.swift
  1 +//
  2 +// EventMonitor.swift
  3 +//
  4 +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +import Foundation
  26 +
  27 +/// Protocol outlining the lifetime events inside Alamofire. It includes both events received from the various
  28 +/// `URLSession` delegate protocols as well as various events from the lifetime of `Request` and its subclasses.
  29 +public protocol EventMonitor {
  30 + /// The `DispatchQueue` onto which Alamofire's root `CompositeEventMonitor` will dispatch events. `.main` by default.
  31 + var queue: DispatchQueue { get }
  32 +
  33 + // MARK: - URLSession Events
  34 +
  35 + // MARK: URLSessionDelegate Events
  36 +
  37 + /// Event called during `URLSessionDelegate`'s `urlSession(_:didBecomeInvalidWithError:)` method.
  38 + func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?)
  39 +
  40 + // MARK: URLSessionTaskDelegate Events
  41 +
  42 + /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didReceive:completionHandler:)` method.
  43 + func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge)
  44 +
  45 + /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)` method.
  46 + func urlSession(_ session: URLSession,
  47 + task: URLSessionTask,
  48 + didSendBodyData bytesSent: Int64,
  49 + totalBytesSent: Int64,
  50 + totalBytesExpectedToSend: Int64)
  51 +
  52 + /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:needNewBodyStream:)` method.
  53 + func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask)
  54 +
  55 + /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` method.
  56 + func urlSession(_ session: URLSession,
  57 + task: URLSessionTask,
  58 + willPerformHTTPRedirection response: HTTPURLResponse,
  59 + newRequest request: URLRequest)
  60 +
  61 + /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didFinishCollecting:)` method.
  62 + func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics)
  63 +
  64 + /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didCompleteWithError:)` method.
  65 + func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
  66 +
  67 + /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:taskIsWaitingForConnectivity:)` method.
  68 + func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask)
  69 +
  70 + // MARK: URLSessionDataDelegate Events
  71 +
  72 + /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:didReceive:)` method.
  73 + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
  74 +
  75 + /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:willCacheResponse:completionHandler:)` method.
  76 + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse)
  77 +
  78 + // MARK: URLSessionDownloadDelegate Events
  79 +
  80 + /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` method.
  81 + func urlSession(_ session: URLSession,
  82 + downloadTask: URLSessionDownloadTask,
  83 + didResumeAtOffset fileOffset: Int64,
  84 + expectedTotalBytes: Int64)
  85 +
  86 + /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)` method.
  87 + func urlSession(_ session: URLSession,
  88 + downloadTask: URLSessionDownloadTask,
  89 + didWriteData bytesWritten: Int64,
  90 + totalBytesWritten: Int64,
  91 + totalBytesExpectedToWrite: Int64)
  92 +
  93 + /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didFinishDownloadingTo:)` method.
  94 + func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
  95 +
  96 + // MARK: - Request Events
  97 +
  98 + /// Event called when a `URLRequest` is first created for a `Request`. If a `RequestAdapter` is active, the
  99 + /// `URLRequest` will be adapted before being issued.
  100 + func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest)
  101 +
  102 + /// Event called when the attempt to create a `URLRequest` from a `Request`'s original `URLRequestConvertible` value fails.
  103 + func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError)
  104 +
  105 + /// Event called when a `RequestAdapter` adapts the `Request`'s initial `URLRequest`.
  106 + func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest)
  107 +
  108 + /// Event called when a `RequestAdapter` fails to adapt the `Request`'s initial `URLRequest`.
  109 + func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError)
  110 +
  111 + /// Event called when a final `URLRequest` is created for a `Request`.
  112 + func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest)
  113 +
  114 + /// Event called when a `URLSessionTask` subclass instance is created for a `Request`.
  115 + func request(_ request: Request, didCreateTask task: URLSessionTask)
  116 +
  117 + /// Event called when a `Request` receives a `URLSessionTaskMetrics` value.
  118 + func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics)
  119 +
  120 + /// Event called when a `Request` fails due to an error created by Alamofire. e.g. When certificate pinning fails.
  121 + func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError)
  122 +
  123 + /// Event called when a `Request`'s task completes, possibly with an error. A `Request` may receive this event
  124 + /// multiple times if it is retried.
  125 + func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?)
  126 +
  127 + /// Event called when a `Request` is about to be retried.
  128 + func requestIsRetrying(_ request: Request)
  129 +
  130 + /// Event called when a `Request` finishes and response serializers are being called.
  131 + func requestDidFinish(_ request: Request)
  132 +
  133 + /// Event called when a `Request` receives a `resume` call.
  134 + func requestDidResume(_ request: Request)
  135 +
  136 + /// Event called when a `Request`'s associated `URLSessionTask` is resumed.
  137 + func request(_ request: Request, didResumeTask task: URLSessionTask)
  138 +
  139 + /// Event called when a `Request` receives a `suspend` call.
  140 + func requestDidSuspend(_ request: Request)
  141 +
  142 + /// Event called when a `Request`'s associated `URLSessionTask` is suspended.
  143 + func request(_ request: Request, didSuspendTask task: URLSessionTask)
  144 +
  145 + /// Event called when a `Request` receives a `cancel` call.
  146 + func requestDidCancel(_ request: Request)
  147 +
  148 + /// Event called when a `Request`'s associated `URLSessionTask` is cancelled.
  149 + func request(_ request: Request, didCancelTask task: URLSessionTask)
  150 +
  151 + // MARK: DataRequest Events
  152 +
  153 + /// Event called when a `DataRequest` calls a `Validation`.
  154 + func request(_ request: DataRequest,
  155 + didValidateRequest urlRequest: URLRequest?,
  156 + response: HTTPURLResponse,
  157 + data: Data?,
  158 + withResult result: Request.ValidationResult)
  159 +
  160 + /// Event called when a `DataRequest` creates a `DataResponse<Data?>` value without calling a `ResponseSerializer`.
  161 + func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>)
  162 +
  163 + /// Event called when a `DataRequest` calls a `ResponseSerializer` and creates a generic `DataResponse<Value, AFError>`.
  164 + func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>)
  165 +
  166 + // MARK: DataStreamRequest Events
  167 +
  168 + /// Event called when a `DataStreamRequest` calls a `Validation` closure.
  169 + ///
  170 + /// - Parameters:
  171 + /// - request: `DataStreamRequest` which is calling the `Validation`.
  172 + /// - urlRequest: `URLRequest` of the request being validated.
  173 + /// - response: `HTTPURLResponse` of the request being validated.
  174 + /// - result: Produced `ValidationResult`.
  175 + func request(_ request: DataStreamRequest,
  176 + didValidateRequest urlRequest: URLRequest?,
  177 + response: HTTPURLResponse,
  178 + withResult result: Request.ValidationResult)
  179 +
  180 + /// Event called when a `DataStreamSerializer` produces a value from streamed `Data`.
  181 + ///
  182 + /// - Parameters:
  183 + /// - request: `DataStreamRequest` for which the value was serialized.
  184 + /// - result: `Result` of the serialization attempt.
  185 + func request<Value>(_ request: DataStreamRequest, didParseStream result: Result<Value, AFError>)
  186 +
  187 + // MARK: UploadRequest Events
  188 +
  189 + /// Event called when an `UploadRequest` creates its `Uploadable` value, indicating the type of upload it represents.
  190 + func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable)
  191 +
  192 + /// Event called when an `UploadRequest` failed to create its `Uploadable` value due to an error.
  193 + func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError)
  194 +
  195 + /// Event called when an `UploadRequest` provides the `InputStream` from its `Uploadable` value. This only occurs if
  196 + /// the `InputStream` does not wrap a `Data` value or file `URL`.
  197 + func request(_ request: UploadRequest, didProvideInputStream stream: InputStream)
  198 +
  199 + // MARK: DownloadRequest Events
  200 +
  201 + /// Event called when a `DownloadRequest`'s `URLSessionDownloadTask` finishes and the temporary file has been moved.
  202 + func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>)
  203 +
  204 + /// Event called when a `DownloadRequest`'s `Destination` closure is called and creates the destination URL the
  205 + /// downloaded file will be moved to.
  206 + func request(_ request: DownloadRequest, didCreateDestinationURL url: URL)
  207 +
  208 + /// Event called when a `DownloadRequest` calls a `Validation`.
  209 + func request(_ request: DownloadRequest,
  210 + didValidateRequest urlRequest: URLRequest?,
  211 + response: HTTPURLResponse,
  212 + fileURL: URL?,
  213 + withResult result: Request.ValidationResult)
  214 +
  215 + /// Event called when a `DownloadRequest` creates a `DownloadResponse<URL?, AFError>` without calling a `ResponseSerializer`.
  216 + func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>)
  217 +
  218 + /// Event called when a `DownloadRequest` calls a `DownloadResponseSerializer` and creates a generic `DownloadResponse<Value, AFError>`
  219 + func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>)
  220 +}
  221 +
  222 +extension EventMonitor {
  223 + /// The default queue on which `CompositeEventMonitor`s will call the `EventMonitor` methods. `.main` by default.
  224 + public var queue: DispatchQueue { .main }
  225 +
  226 + // MARK: Default Implementations
  227 +
  228 + public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {}
  229 + public func urlSession(_ session: URLSession,
  230 + task: URLSessionTask,
  231 + didReceive challenge: URLAuthenticationChallenge) {}
  232 + public func urlSession(_ session: URLSession,
  233 + task: URLSessionTask,
  234 + didSendBodyData bytesSent: Int64,
  235 + totalBytesSent: Int64,
  236 + totalBytesExpectedToSend: Int64) {}
  237 + public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {}
  238 + public func urlSession(_ session: URLSession,
  239 + task: URLSessionTask,
  240 + willPerformHTTPRedirection response: HTTPURLResponse,
  241 + newRequest request: URLRequest) {}
  242 + public func urlSession(_ session: URLSession,
  243 + task: URLSessionTask,
  244 + didFinishCollecting metrics: URLSessionTaskMetrics) {}
  245 + public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {}
  246 + public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {}
  247 + public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
  248 + public func urlSession(_ session: URLSession,
  249 + dataTask: URLSessionDataTask,
  250 + willCacheResponse proposedResponse: CachedURLResponse) {}
  251 + public func urlSession(_ session: URLSession,
  252 + downloadTask: URLSessionDownloadTask,
  253 + didResumeAtOffset fileOffset: Int64,
  254 + expectedTotalBytes: Int64) {}
  255 + public func urlSession(_ session: URLSession,
  256 + downloadTask: URLSessionDownloadTask,
  257 + didWriteData bytesWritten: Int64,
  258 + totalBytesWritten: Int64,
  259 + totalBytesExpectedToWrite: Int64) {}
  260 + public func urlSession(_ session: URLSession,
  261 + downloadTask: URLSessionDownloadTask,
  262 + didFinishDownloadingTo location: URL) {}
  263 + public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {}
  264 + public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {}
  265 + public func request(_ request: Request,
  266 + didAdaptInitialRequest initialRequest: URLRequest,
  267 + to adaptedRequest: URLRequest) {}
  268 + public func request(_ request: Request,
  269 + didFailToAdaptURLRequest initialRequest: URLRequest,
  270 + withError error: AFError) {}
  271 + public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {}
  272 + public func request(_ request: Request, didCreateTask task: URLSessionTask) {}
  273 + public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {}
  274 + public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {}
  275 + public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {}
  276 + public func requestIsRetrying(_ request: Request) {}
  277 + public func requestDidFinish(_ request: Request) {}
  278 + public func requestDidResume(_ request: Request) {}
  279 + public func request(_ request: Request, didResumeTask task: URLSessionTask) {}
  280 + public func requestDidSuspend(_ request: Request) {}
  281 + public func request(_ request: Request, didSuspendTask task: URLSessionTask) {}
  282 + public func requestDidCancel(_ request: Request) {}
  283 + public func request(_ request: Request, didCancelTask task: URLSessionTask) {}
  284 + public func request(_ request: DataRequest,
  285 + didValidateRequest urlRequest: URLRequest?,
  286 + response: HTTPURLResponse,
  287 + data: Data?,
  288 + withResult result: Request.ValidationResult) {}
  289 + public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {}
  290 + public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {}
  291 + public func request(_ request: DataStreamRequest,
  292 + didValidateRequest urlRequest: URLRequest?,
  293 + response: HTTPURLResponse,
  294 + withResult result: Request.ValidationResult) {}
  295 + public func request<Value>(_ request: DataStreamRequest, didParseStream result: Result<Value, AFError>) {}
  296 + public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {}
  297 + public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {}
  298 + public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {}
  299 + public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {}
  300 + public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {}
  301 + public func request(_ request: DownloadRequest,
  302 + didValidateRequest urlRequest: URLRequest?,
  303 + response: HTTPURLResponse,
  304 + fileURL: URL?,
  305 + withResult result: Request.ValidationResult) {}
  306 + public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {}
  307 + public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {}
  308 +}
  309 +
  310 +/// An `EventMonitor` which can contain multiple `EventMonitor`s and calls their methods on their queues.
  311 +public final class CompositeEventMonitor: EventMonitor {
  312 + public let queue = DispatchQueue(label: "org.alamofire.compositeEventMonitor", qos: .utility)
  313 +
  314 + let monitors: [EventMonitor]
  315 +
  316 + init(monitors: [EventMonitor]) {
  317 + self.monitors = monitors
  318 + }
  319 +
  320 + func performEvent(_ event: @escaping (EventMonitor) -> Void) {
  321 + queue.async {
  322 + for monitor in self.monitors {
  323 + monitor.queue.async { event(monitor) }
  324 + }
  325 + }
  326 + }
  327 +
  328 + public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
  329 + performEvent { $0.urlSession(session, didBecomeInvalidWithError: error) }
  330 + }
  331 +
  332 + public func urlSession(_ session: URLSession,
  333 + task: URLSessionTask,
  334 + didReceive challenge: URLAuthenticationChallenge) {
  335 + performEvent { $0.urlSession(session, task: task, didReceive: challenge) }
  336 + }
  337 +
  338 + public func urlSession(_ session: URLSession,
  339 + task: URLSessionTask,
  340 + didSendBodyData bytesSent: Int64,
  341 + totalBytesSent: Int64,
  342 + totalBytesExpectedToSend: Int64) {
  343 + performEvent {
  344 + $0.urlSession(session,
  345 + task: task,
  346 + didSendBodyData: bytesSent,
  347 + totalBytesSent: totalBytesSent,
  348 + totalBytesExpectedToSend: totalBytesExpectedToSend)
  349 + }
  350 + }
  351 +
  352 + public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
  353 + performEvent {
  354 + $0.urlSession(session, taskNeedsNewBodyStream: task)
  355 + }
  356 + }
  357 +
  358 + public func urlSession(_ session: URLSession,
  359 + task: URLSessionTask,
  360 + willPerformHTTPRedirection response: HTTPURLResponse,
  361 + newRequest request: URLRequest) {
  362 + performEvent {
  363 + $0.urlSession(session,
  364 + task: task,
  365 + willPerformHTTPRedirection: response,
  366 + newRequest: request)
  367 + }
  368 + }
  369 +
  370 + public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
  371 + performEvent { $0.urlSession(session, task: task, didFinishCollecting: metrics) }
  372 + }
  373 +
  374 + public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
  375 + performEvent { $0.urlSession(session, task: task, didCompleteWithError: error) }
  376 + }
  377 +
  378 + @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
  379 + public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
  380 + performEvent { $0.urlSession(session, taskIsWaitingForConnectivity: task) }
  381 + }
  382 +
  383 + public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
  384 + performEvent { $0.urlSession(session, dataTask: dataTask, didReceive: data) }
  385 + }
  386 +
  387 + public func urlSession(_ session: URLSession,
  388 + dataTask: URLSessionDataTask,
  389 + willCacheResponse proposedResponse: CachedURLResponse) {
  390 + performEvent { $0.urlSession(session, dataTask: dataTask, willCacheResponse: proposedResponse) }
  391 + }
  392 +
  393 + public func urlSession(_ session: URLSession,
  394 + downloadTask: URLSessionDownloadTask,
  395 + didResumeAtOffset fileOffset: Int64,
  396 + expectedTotalBytes: Int64) {
  397 + performEvent {
  398 + $0.urlSession(session,
  399 + downloadTask: downloadTask,
  400 + didResumeAtOffset: fileOffset,
  401 + expectedTotalBytes: expectedTotalBytes)
  402 + }
  403 + }
  404 +
  405 + public func urlSession(_ session: URLSession,
  406 + downloadTask: URLSessionDownloadTask,
  407 + didWriteData bytesWritten: Int64,
  408 + totalBytesWritten: Int64,
  409 + totalBytesExpectedToWrite: Int64) {
  410 + performEvent {
  411 + $0.urlSession(session,
  412 + downloadTask: downloadTask,
  413 + didWriteData: bytesWritten,
  414 + totalBytesWritten: totalBytesWritten,
  415 + totalBytesExpectedToWrite: totalBytesExpectedToWrite)
  416 + }
  417 + }
  418 +
  419 + public func urlSession(_ session: URLSession,
  420 + downloadTask: URLSessionDownloadTask,
  421 + didFinishDownloadingTo location: URL) {
  422 + performEvent { $0.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location) }
  423 + }
  424 +
  425 + public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
  426 + performEvent { $0.request(request, didCreateInitialURLRequest: urlRequest) }
  427 + }
  428 +
  429 + public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
  430 + performEvent { $0.request(request, didFailToCreateURLRequestWithError: error) }
  431 + }
  432 +
  433 + public func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
  434 + performEvent { $0.request(request, didAdaptInitialRequest: initialRequest, to: adaptedRequest) }
  435 + }
  436 +
  437 + public func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
  438 + performEvent { $0.request(request, didFailToAdaptURLRequest: initialRequest, withError: error) }
  439 + }
  440 +
  441 + public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
  442 + performEvent { $0.request(request, didCreateURLRequest: urlRequest) }
  443 + }
  444 +
  445 + public func request(_ request: Request, didCreateTask task: URLSessionTask) {
  446 + performEvent { $0.request(request, didCreateTask: task) }
  447 + }
  448 +
  449 + public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
  450 + performEvent { $0.request(request, didGatherMetrics: metrics) }
  451 + }
  452 +
  453 + public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
  454 + performEvent { $0.request(request, didFailTask: task, earlyWithError: error) }
  455 + }
  456 +
  457 + public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
  458 + performEvent { $0.request(request, didCompleteTask: task, with: error) }
  459 + }
  460 +
  461 + public func requestIsRetrying(_ request: Request) {
  462 + performEvent { $0.requestIsRetrying(request) }
  463 + }
  464 +
  465 + public func requestDidFinish(_ request: Request) {
  466 + performEvent { $0.requestDidFinish(request) }
  467 + }
  468 +
  469 + public func requestDidResume(_ request: Request) {
  470 + performEvent { $0.requestDidResume(request) }
  471 + }
  472 +
  473 + public func request(_ request: Request, didResumeTask task: URLSessionTask) {
  474 + performEvent { $0.request(request, didResumeTask: task) }
  475 + }
  476 +
  477 + public func requestDidSuspend(_ request: Request) {
  478 + performEvent { $0.requestDidSuspend(request) }
  479 + }
  480 +
  481 + public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
  482 + performEvent { $0.request(request, didSuspendTask: task) }
  483 + }
  484 +
  485 + public func requestDidCancel(_ request: Request) {
  486 + performEvent { $0.requestDidCancel(request) }
  487 + }
  488 +
  489 + public func request(_ request: Request, didCancelTask task: URLSessionTask) {
  490 + performEvent { $0.request(request, didCancelTask: task) }
  491 + }
  492 +
  493 + public func request(_ request: DataRequest,
  494 + didValidateRequest urlRequest: URLRequest?,
  495 + response: HTTPURLResponse,
  496 + data: Data?,
  497 + withResult result: Request.ValidationResult) {
  498 + performEvent { $0.request(request,
  499 + didValidateRequest: urlRequest,
  500 + response: response,
  501 + data: data,
  502 + withResult: result)
  503 + }
  504 + }
  505 +
  506 + public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
  507 + performEvent { $0.request(request, didParseResponse: response) }
  508 + }
  509 +
  510 + public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {
  511 + performEvent { $0.request(request, didParseResponse: response) }
  512 + }
  513 +
  514 + public func request(_ request: DataStreamRequest,
  515 + didValidateRequest urlRequest: URLRequest?,
  516 + response: HTTPURLResponse,
  517 + withResult result: Request.ValidationResult) {
  518 + performEvent { $0.request(request,
  519 + didValidateRequest: urlRequest,
  520 + response: response,
  521 + withResult: result)
  522 + }
  523 + }
  524 +
  525 + public func request<Value>(_ request: DataStreamRequest, didParseStream result: Result<Value, AFError>) {
  526 + performEvent { $0.request(request, didParseStream: result) }
  527 + }
  528 +
  529 + public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
  530 + performEvent { $0.request(request, didCreateUploadable: uploadable) }
  531 + }
  532 +
  533 + public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
  534 + performEvent { $0.request(request, didFailToCreateUploadableWithError: error) }
  535 + }
  536 +
  537 + public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
  538 + performEvent { $0.request(request, didProvideInputStream: stream) }
  539 + }
  540 +
  541 + public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
  542 + performEvent { $0.request(request, didFinishDownloadingUsing: task, with: result) }
  543 + }
  544 +
  545 + public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
  546 + performEvent { $0.request(request, didCreateDestinationURL: url) }
  547 + }
  548 +
  549 + public func request(_ request: DownloadRequest,
  550 + didValidateRequest urlRequest: URLRequest?,
  551 + response: HTTPURLResponse,
  552 + fileURL: URL?,
  553 + withResult result: Request.ValidationResult) {
  554 + performEvent { $0.request(request,
  555 + didValidateRequest: urlRequest,
  556 + response: response,
  557 + fileURL: fileURL,
  558 + withResult: result) }
  559 + }
  560 +
  561 + public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
  562 + performEvent { $0.request(request, didParseResponse: response) }
  563 + }
  564 +
  565 + public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {
  566 + performEvent { $0.request(request, didParseResponse: response) }
  567 + }
  568 +}
  569 +
  570 +/// `EventMonitor` that allows optional closures to be set to receive events.
  571 +open class ClosureEventMonitor: EventMonitor {
  572 + /// Closure called on the `urlSession(_:didBecomeInvalidWithError:)` event.
  573 + open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
  574 +
  575 + /// Closure called on the `urlSession(_:task:didReceive:completionHandler:)`.
  576 + open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> Void)?
  577 +
  578 + /// Closure that receives `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)` event.
  579 + open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
  580 +
  581 + /// Closure called on the `urlSession(_:task:needNewBodyStream:)` event.
  582 + open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> Void)?
  583 +
  584 + /// Closure called on the `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` event.
  585 + open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> Void)?
  586 +
  587 + /// Closure called on the `urlSession(_:task:didFinishCollecting:)` event.
  588 + open var taskDidFinishCollectingMetrics: ((URLSession, URLSessionTask, URLSessionTaskMetrics) -> Void)?
  589 +
  590 + /// Closure called on the `urlSession(_:task:didCompleteWithError:)` event.
  591 + open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)?
  592 +
  593 + /// Closure called on the `urlSession(_:taskIsWaitingForConnectivity:)` event.
  594 + open var taskIsWaitingForConnectivity: ((URLSession, URLSessionTask) -> Void)?
  595 +
  596 + /// Closure that receives the `urlSession(_:dataTask:didReceive:)` event.
  597 + open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
  598 +
  599 + /// Closure called on the `urlSession(_:dataTask:willCacheResponse:completionHandler:)` event.
  600 + open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> Void)?
  601 +
  602 + /// Closure called on the `urlSession(_:downloadTask:didFinishDownloadingTo:)` event.
  603 + open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)?
  604 +
  605 + /// Closure called on the `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`
  606 + /// event.
  607 + open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
  608 +
  609 + /// Closure called on the `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` event.
  610 + open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
  611 +
  612 + // MARK: - Request Events
  613 +
  614 + /// Closure called on the `request(_:didCreateInitialURLRequest:)` event.
  615 + open var requestDidCreateInitialURLRequest: ((Request, URLRequest) -> Void)?
  616 +
  617 + /// Closure called on the `request(_:didFailToCreateURLRequestWithError:)` event.
  618 + open var requestDidFailToCreateURLRequestWithError: ((Request, AFError) -> Void)?
  619 +
  620 + /// Closure called on the `request(_:didAdaptInitialRequest:to:)` event.
  621 + open var requestDidAdaptInitialRequestToAdaptedRequest: ((Request, URLRequest, URLRequest) -> Void)?
  622 +
  623 + /// Closure called on the `request(_:didFailToAdaptURLRequest:withError:)` event.
  624 + open var requestDidFailToAdaptURLRequestWithError: ((Request, URLRequest, AFError) -> Void)?
  625 +
  626 + /// Closure called on the `request(_:didCreateURLRequest:)` event.
  627 + open var requestDidCreateURLRequest: ((Request, URLRequest) -> Void)?
  628 +
  629 + /// Closure called on the `request(_:didCreateTask:)` event.
  630 + open var requestDidCreateTask: ((Request, URLSessionTask) -> Void)?
  631 +
  632 + /// Closure called on the `request(_:didGatherMetrics:)` event.
  633 + open var requestDidGatherMetrics: ((Request, URLSessionTaskMetrics) -> Void)?
  634 +
  635 + /// Closure called on the `request(_:didFailTask:earlyWithError:)` event.
  636 + open var requestDidFailTaskEarlyWithError: ((Request, URLSessionTask, AFError) -> Void)?
  637 +
  638 + /// Closure called on the `request(_:didCompleteTask:with:)` event.
  639 + open var requestDidCompleteTaskWithError: ((Request, URLSessionTask, AFError?) -> Void)?
  640 +
  641 + /// Closure called on the `requestIsRetrying(_:)` event.
  642 + open var requestIsRetrying: ((Request) -> Void)?
  643 +
  644 + /// Closure called on the `requestDidFinish(_:)` event.
  645 + open var requestDidFinish: ((Request) -> Void)?
  646 +
  647 + /// Closure called on the `requestDidResume(_:)` event.
  648 + open var requestDidResume: ((Request) -> Void)?
  649 +
  650 + /// Closure called on the `request(_:didResumeTask:)` event.
  651 + open var requestDidResumeTask: ((Request, URLSessionTask) -> Void)?
  652 +
  653 + /// Closure called on the `requestDidSuspend(_:)` event.
  654 + open var requestDidSuspend: ((Request) -> Void)?
  655 +
  656 + /// Closure called on the `request(_:didSuspendTask:)` event.
  657 + open var requestDidSuspendTask: ((Request, URLSessionTask) -> Void)?
  658 +
  659 + /// Closure called on the `requestDidCancel(_:)` event.
  660 + open var requestDidCancel: ((Request) -> Void)?
  661 +
  662 + /// Closure called on the `request(_:didCancelTask:)` event.
  663 + open var requestDidCancelTask: ((Request, URLSessionTask) -> Void)?
  664 +
  665 + /// Closure called on the `request(_:didValidateRequest:response:data:withResult:)` event.
  666 + open var requestDidValidateRequestResponseDataWithResult: ((DataRequest, URLRequest?, HTTPURLResponse, Data?, Request.ValidationResult) -> Void)?
  667 +
  668 + /// Closure called on the `request(_:didParseResponse:)` event.
  669 + open var requestDidParseResponse: ((DataRequest, DataResponse<Data?, AFError>) -> Void)?
  670 +
  671 + /// Closure called on the `request(_:didValidateRequest:response:withResult:)` event.
  672 + open var requestDidValidateRequestResponseWithResult: ((DataStreamRequest, URLRequest?, HTTPURLResponse, Request.ValidationResult) -> Void)?
  673 +
  674 + /// Closure called on the `request(_:didCreateUploadable:)` event.
  675 + open var requestDidCreateUploadable: ((UploadRequest, UploadRequest.Uploadable) -> Void)?
  676 +
  677 + /// Closure called on the `request(_:didFailToCreateUploadableWithError:)` event.
  678 + open var requestDidFailToCreateUploadableWithError: ((UploadRequest, AFError) -> Void)?
  679 +
  680 + /// Closure called on the `request(_:didProvideInputStream:)` event.
  681 + open var requestDidProvideInputStream: ((UploadRequest, InputStream) -> Void)?
  682 +
  683 + /// Closure called on the `request(_:didFinishDownloadingUsing:with:)` event.
  684 + open var requestDidFinishDownloadingUsingTaskWithResult: ((DownloadRequest, URLSessionTask, Result<URL, AFError>) -> Void)?
  685 +
  686 + /// Closure called on the `request(_:didCreateDestinationURL:)` event.
  687 + open var requestDidCreateDestinationURL: ((DownloadRequest, URL) -> Void)?
  688 +
  689 + /// Closure called on the `request(_:didValidateRequest:response:temporaryURL:destinationURL:withResult:)` event.
  690 + open var requestDidValidateRequestResponseFileURLWithResult: ((DownloadRequest, URLRequest?, HTTPURLResponse, URL?, Request.ValidationResult) -> Void)?
  691 +
  692 + /// Closure called on the `request(_:didParseResponse:)` event.
  693 + open var requestDidParseDownloadResponse: ((DownloadRequest, DownloadResponse<URL?, AFError>) -> Void)?
  694 +
  695 + public let queue: DispatchQueue
  696 +
  697 + /// Creates an instance using the provided queue.
  698 + ///
  699 + /// - Parameter queue: `DispatchQueue` on which events will fired. `.main` by default.
  700 + public init(queue: DispatchQueue = .main) {
  701 + self.queue = queue
  702 + }
  703 +
  704 + open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
  705 + sessionDidBecomeInvalidWithError?(session, error)
  706 + }
  707 +
  708 + open func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge) {
  709 + taskDidReceiveChallenge?(session, task, challenge)
  710 + }
  711 +
  712 + open func urlSession(_ session: URLSession,
  713 + task: URLSessionTask,
  714 + didSendBodyData bytesSent: Int64,
  715 + totalBytesSent: Int64,
  716 + totalBytesExpectedToSend: Int64) {
  717 + taskDidSendBodyData?(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
  718 + }
  719 +
  720 + open func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
  721 + taskNeedNewBodyStream?(session, task)
  722 + }
  723 +
  724 + open func urlSession(_ session: URLSession,
  725 + task: URLSessionTask,
  726 + willPerformHTTPRedirection response: HTTPURLResponse,
  727 + newRequest request: URLRequest) {
  728 + taskWillPerformHTTPRedirection?(session, task, response, request)
  729 + }
  730 +
  731 + open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
  732 + taskDidFinishCollectingMetrics?(session, task, metrics)
  733 + }
  734 +
  735 + open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
  736 + taskDidComplete?(session, task, error)
  737 + }
  738 +
  739 + @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
  740 + open func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
  741 + taskIsWaitingForConnectivity?(session, task)
  742 + }
  743 +
  744 + open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
  745 + dataTaskDidReceiveData?(session, dataTask, data)
  746 + }
  747 +
  748 + open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse) {
  749 + dataTaskWillCacheResponse?(session, dataTask, proposedResponse)
  750 + }
  751 +
  752 + open func urlSession(_ session: URLSession,
  753 + downloadTask: URLSessionDownloadTask,
  754 + didResumeAtOffset fileOffset: Int64,
  755 + expectedTotalBytes: Int64) {
  756 + downloadTaskDidResumeAtOffset?(session, downloadTask, fileOffset, expectedTotalBytes)
  757 + }
  758 +
  759 + open func urlSession(_ session: URLSession,
  760 + downloadTask: URLSessionDownloadTask,
  761 + didWriteData bytesWritten: Int64,
  762 + totalBytesWritten: Int64,
  763 + totalBytesExpectedToWrite: Int64) {
  764 + downloadTaskDidWriteData?(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
  765 + }
  766 +
  767 + open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
  768 + downloadTaskDidFinishDownloadingToURL?(session, downloadTask, location)
  769 + }
  770 +
  771 + // MARK: Request Events
  772 +
  773 + open func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
  774 + requestDidCreateInitialURLRequest?(request, urlRequest)
  775 + }
  776 +
  777 + open func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
  778 + requestDidFailToCreateURLRequestWithError?(request, error)
  779 + }
  780 +
  781 + open func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
  782 + requestDidAdaptInitialRequestToAdaptedRequest?(request, initialRequest, adaptedRequest)
  783 + }
  784 +
  785 + open func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
  786 + requestDidFailToAdaptURLRequestWithError?(request, initialRequest, error)
  787 + }
  788 +
  789 + open func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
  790 + requestDidCreateURLRequest?(request, urlRequest)
  791 + }
  792 +
  793 + open func request(_ request: Request, didCreateTask task: URLSessionTask) {
  794 + requestDidCreateTask?(request, task)
  795 + }
  796 +
  797 + open func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
  798 + requestDidGatherMetrics?(request, metrics)
  799 + }
  800 +
  801 + open func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
  802 + requestDidFailTaskEarlyWithError?(request, task, error)
  803 + }
  804 +
  805 + open func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
  806 + requestDidCompleteTaskWithError?(request, task, error)
  807 + }
  808 +
  809 + open func requestIsRetrying(_ request: Request) {
  810 + requestIsRetrying?(request)
  811 + }
  812 +
  813 + open func requestDidFinish(_ request: Request) {
  814 + requestDidFinish?(request)
  815 + }
  816 +
  817 + open func requestDidResume(_ request: Request) {
  818 + requestDidResume?(request)
  819 + }
  820 +
  821 + public func request(_ request: Request, didResumeTask task: URLSessionTask) {
  822 + requestDidResumeTask?(request, task)
  823 + }
  824 +
  825 + open func requestDidSuspend(_ request: Request) {
  826 + requestDidSuspend?(request)
  827 + }
  828 +
  829 + public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
  830 + requestDidSuspendTask?(request, task)
  831 + }
  832 +
  833 + open func requestDidCancel(_ request: Request) {
  834 + requestDidCancel?(request)
  835 + }
  836 +
  837 + public func request(_ request: Request, didCancelTask task: URLSessionTask) {
  838 + requestDidCancelTask?(request, task)
  839 + }
  840 +
  841 + open func request(_ request: DataRequest,
  842 + didValidateRequest urlRequest: URLRequest?,
  843 + response: HTTPURLResponse,
  844 + data: Data?,
  845 + withResult result: Request.ValidationResult) {
  846 + requestDidValidateRequestResponseDataWithResult?(request, urlRequest, response, data, result)
  847 + }
  848 +
  849 + open func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
  850 + requestDidParseResponse?(request, response)
  851 + }
  852 +
  853 + public func request(_ request: DataStreamRequest, didValidateRequest urlRequest: URLRequest?, response: HTTPURLResponse, withResult result: Request.ValidationResult) {
  854 + requestDidValidateRequestResponseWithResult?(request, urlRequest, response, result)
  855 + }
  856 +
  857 + open func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
  858 + requestDidCreateUploadable?(request, uploadable)
  859 + }
  860 +
  861 + open func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
  862 + requestDidFailToCreateUploadableWithError?(request, error)
  863 + }
  864 +
  865 + open func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
  866 + requestDidProvideInputStream?(request, stream)
  867 + }
  868 +
  869 + open func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
  870 + requestDidFinishDownloadingUsingTaskWithResult?(request, task, result)
  871 + }
  872 +
  873 + open func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
  874 + requestDidCreateDestinationURL?(request, url)
  875 + }
  876 +
  877 + open func request(_ request: DownloadRequest,
  878 + didValidateRequest urlRequest: URLRequest?,
  879 + response: HTTPURLResponse,
  880 + fileURL: URL?,
  881 + withResult result: Request.ValidationResult) {
  882 + requestDidValidateRequestResponseFileURLWithResult?(request,
  883 + urlRequest,
  884 + response,
  885 + fileURL,
  886 + result)
  887 + }
  888 +
  889 + open func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
  890 + requestDidParseDownloadResponse?(request, response)
  891 + }
  892 +}
Pods/Alamofire/Source/HTTPHeaders.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/HTTPHeaders.swift
  1 +//
  2 +// HTTPHeaders.swift
  3 +//
  4 +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +import Foundation
  26 +
  27 +/// An order-preserving and case-insensitive representation of HTTP headers.
  28 +public struct HTTPHeaders {
  29 + private var headers: [HTTPHeader] = []
  30 +
  31 + /// Creates an empty instance.
  32 + public init() {}
  33 +
  34 + /// Creates an instance from an array of `HTTPHeader`s. Duplicate case-insensitive names are collapsed into the last
  35 + /// name and value encountered.
  36 + public init(_ headers: [HTTPHeader]) {
  37 + self.init()
  38 +
  39 + headers.forEach { update($0) }
  40 + }
  41 +
  42 + /// Creates an instance from a `[String: String]`. Duplicate case-insensitive names are collapsed into the last name
  43 + /// and value encountered.
  44 + public init(_ dictionary: [String: String]) {
  45 + self.init()
  46 +
  47 + dictionary.forEach { update(HTTPHeader(name: $0.key, value: $0.value)) }
  48 + }
  49 +
  50 + /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
  51 + ///
  52 + /// - Parameters:
  53 + /// - name: The `HTTPHeader` name.
  54 + /// - value: The `HTTPHeader value.
  55 + public mutating func add(name: String, value: String) {
  56 + update(HTTPHeader(name: name, value: value))
  57 + }
  58 +
  59 + /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
  60 + ///
  61 + /// - Parameter header: The `HTTPHeader` to update or append.
  62 + public mutating func add(_ header: HTTPHeader) {
  63 + update(header)
  64 + }
  65 +
  66 + /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
  67 + ///
  68 + /// - Parameters:
  69 + /// - name: The `HTTPHeader` name.
  70 + /// - value: The `HTTPHeader value.
  71 + public mutating func update(name: String, value: String) {
  72 + update(HTTPHeader(name: name, value: value))
  73 + }
  74 +
  75 + /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
  76 + ///
  77 + /// - Parameter header: The `HTTPHeader` to update or append.
  78 + public mutating func update(_ header: HTTPHeader) {
  79 + guard let index = headers.index(of: header.name) else {
  80 + headers.append(header)
  81 + return
  82 + }
  83 +
  84 + headers.replaceSubrange(index...index, with: [header])
  85 + }
  86 +
  87 + /// Case-insensitively removes an `HTTPHeader`, if it exists, from the instance.
  88 + ///
  89 + /// - Parameter name: The name of the `HTTPHeader` to remove.
  90 + public mutating func remove(name: String) {
  91 + guard let index = headers.index(of: name) else { return }
  92 +
  93 + headers.remove(at: index)
  94 + }
  95 +
  96 + /// Sort the current instance by header name, case insensitively.
  97 + public mutating func sort() {
  98 + headers.sort { $0.name.lowercased() < $1.name.lowercased() }
  99 + }
  100 +
  101 + /// Returns an instance sorted by header name.
  102 + ///
  103 + /// - Returns: A copy of the current instance sorted by name.
  104 + public func sorted() -> HTTPHeaders {
  105 + var headers = self
  106 + headers.sort()
  107 +
  108 + return headers
  109 + }
  110 +
  111 + /// Case-insensitively find a header's value by name.
  112 + ///
  113 + /// - Parameter name: The name of the header to search for, case-insensitively.
  114 + ///
  115 + /// - Returns: The value of header, if it exists.
  116 + public func value(for name: String) -> String? {
  117 + guard let index = headers.index(of: name) else { return nil }
  118 +
  119 + return headers[index].value
  120 + }
  121 +
  122 + /// Case-insensitively access the header with the given name.
  123 + ///
  124 + /// - Parameter name: The name of the header.
  125 + public subscript(_ name: String) -> String? {
  126 + get { value(for: name) }
  127 + set {
  128 + if let value = newValue {
  129 + update(name: name, value: value)
  130 + } else {
  131 + remove(name: name)
  132 + }
  133 + }
  134 + }
  135 +
  136 + /// The dictionary representation of all headers.
  137 + ///
  138 + /// This representation does not preserve the current order of the instance.
  139 + public var dictionary: [String: String] {
  140 + let namesAndValues = headers.map { ($0.name, $0.value) }
  141 +
  142 + return Dictionary(namesAndValues, uniquingKeysWith: { _, last in last })
  143 + }
  144 +}
  145 +
  146 +extension HTTPHeaders: ExpressibleByDictionaryLiteral {
  147 + public init(dictionaryLiteral elements: (String, String)...) {
  148 + self.init()
  149 +
  150 + elements.forEach { update(name: $0.0, value: $0.1) }
  151 + }
  152 +}
  153 +
  154 +extension HTTPHeaders: ExpressibleByArrayLiteral {
  155 + public init(arrayLiteral elements: HTTPHeader...) {
  156 + self.init(elements)
  157 + }
  158 +}
  159 +
  160 +extension HTTPHeaders: Sequence {
  161 + public func makeIterator() -> IndexingIterator<[HTTPHeader]> {
  162 + headers.makeIterator()
  163 + }
  164 +}
  165 +
  166 +extension HTTPHeaders: Collection {
  167 + public var startIndex: Int {
  168 + headers.startIndex
  169 + }
  170 +
  171 + public var endIndex: Int {
  172 + headers.endIndex
  173 + }
  174 +
  175 + public subscript(position: Int) -> HTTPHeader {
  176 + headers[position]
  177 + }
  178 +
  179 + public func index(after i: Int) -> Int {
  180 + headers.index(after: i)
  181 + }
  182 +}
  183 +
  184 +extension HTTPHeaders: CustomStringConvertible {
  185 + public var description: String {
  186 + headers.map(\.description)
  187 + .joined(separator: "\n")
  188 + }
  189 +}
  190 +
  191 +// MARK: - HTTPHeader
  192 +
  193 +/// A representation of a single HTTP header's name / value pair.
  194 +public struct HTTPHeader: Hashable {
  195 + /// Name of the header.
  196 + public let name: String
  197 +
  198 + /// Value of the header.
  199 + public let value: String
  200 +
  201 + /// Creates an instance from the given `name` and `value`.
  202 + ///
  203 + /// - Parameters:
  204 + /// - name: The name of the header.
  205 + /// - value: The value of the header.
  206 + public init(name: String, value: String) {
  207 + self.name = name
  208 + self.value = value
  209 + }
  210 +}
  211 +
  212 +extension HTTPHeader: CustomStringConvertible {
  213 + public var description: String {
  214 + "\(name): \(value)"
  215 + }
  216 +}
  217 +
  218 +extension HTTPHeader {
  219 + /// Returns an `Accept` header.
  220 + ///
  221 + /// - Parameter value: The `Accept` value.
  222 + /// - Returns: The header.
  223 + public static func accept(_ value: String) -> HTTPHeader {
  224 + HTTPHeader(name: "Accept", value: value)
  225 + }
  226 +
  227 + /// Returns an `Accept-Charset` header.
  228 + ///
  229 + /// - Parameter value: The `Accept-Charset` value.
  230 + /// - Returns: The header.
  231 + public static func acceptCharset(_ value: String) -> HTTPHeader {
  232 + HTTPHeader(name: "Accept-Charset", value: value)
  233 + }
  234 +
  235 + /// Returns an `Accept-Language` header.
  236 + ///
  237 + /// Alamofire offers a default Accept-Language header that accumulates and encodes the system's preferred languages.
  238 + /// Use `HTTPHeader.defaultAcceptLanguage`.
  239 + ///
  240 + /// - Parameter value: The `Accept-Language` value.
  241 + ///
  242 + /// - Returns: The header.
  243 + public static func acceptLanguage(_ value: String) -> HTTPHeader {
  244 + HTTPHeader(name: "Accept-Language", value: value)
  245 + }
  246 +
  247 + /// Returns an `Accept-Encoding` header.
  248 + ///
  249 + /// Alamofire offers a default accept encoding value that provides the most common values. Use
  250 + /// `HTTPHeader.defaultAcceptEncoding`.
  251 + ///
  252 + /// - Parameter value: The `Accept-Encoding` value.
  253 + ///
  254 + /// - Returns: The header
  255 + public static func acceptEncoding(_ value: String) -> HTTPHeader {
  256 + HTTPHeader(name: "Accept-Encoding", value: value)
  257 + }
  258 +
  259 + /// Returns a `Basic` `Authorization` header using the `username` and `password` provided.
  260 + ///
  261 + /// - Parameters:
  262 + /// - username: The username of the header.
  263 + /// - password: The password of the header.
  264 + ///
  265 + /// - Returns: The header.
  266 + public static func authorization(username: String, password: String) -> HTTPHeader {
  267 + let credential = Data("\(username):\(password)".utf8).base64EncodedString()
  268 +
  269 + return authorization("Basic \(credential)")
  270 + }
  271 +
  272 + /// Returns a `Bearer` `Authorization` header using the `bearerToken` provided
  273 + ///
  274 + /// - Parameter bearerToken: The bearer token.
  275 + ///
  276 + /// - Returns: The header.
  277 + public static func authorization(bearerToken: String) -> HTTPHeader {
  278 + authorization("Bearer \(bearerToken)")
  279 + }
  280 +
  281 + /// Returns an `Authorization` header.
  282 + ///
  283 + /// Alamofire provides built-in methods to produce `Authorization` headers. For a Basic `Authorization` header use
  284 + /// `HTTPHeader.authorization(username:password:)`. For a Bearer `Authorization` header, use
  285 + /// `HTTPHeader.authorization(bearerToken:)`.
  286 + ///
  287 + /// - Parameter value: The `Authorization` value.
  288 + ///
  289 + /// - Returns: The header.
  290 + public static func authorization(_ value: String) -> HTTPHeader {
  291 + HTTPHeader(name: "Authorization", value: value)
  292 + }
  293 +
  294 + /// Returns a `Content-Disposition` header.
  295 + ///
  296 + /// - Parameter value: The `Content-Disposition` value.
  297 + ///
  298 + /// - Returns: The header.
  299 + public static func contentDisposition(_ value: String) -> HTTPHeader {
  300 + HTTPHeader(name: "Content-Disposition", value: value)
  301 + }
  302 +
  303 + /// Returns a `Content-Encoding` header.
  304 + ///
  305 + /// - Parameter value: The `Content-Encoding`.
  306 + ///
  307 + /// - Returns: The header.
  308 + public static func contentEncoding(_ value: String) -> HTTPHeader {
  309 + HTTPHeader(name: "Content-Encoding", value: value)
  310 + }
  311 +
  312 + /// Returns a `Content-Type` header.
  313 + ///
  314 + /// All Alamofire `ParameterEncoding`s and `ParameterEncoder`s set the `Content-Type` of the request, so it may not
  315 + /// be necessary to manually set this value.
  316 + ///
  317 + /// - Parameter value: The `Content-Type` value.
  318 + ///
  319 + /// - Returns: The header.
  320 + public static func contentType(_ value: String) -> HTTPHeader {
  321 + HTTPHeader(name: "Content-Type", value: value)
  322 + }
  323 +
  324 + /// Returns a `User-Agent` header.
  325 + ///
  326 + /// - Parameter value: The `User-Agent` value.
  327 + ///
  328 + /// - Returns: The header.
  329 + public static func userAgent(_ value: String) -> HTTPHeader {
  330 + HTTPHeader(name: "User-Agent", value: value)
  331 + }
  332 +}
  333 +
  334 +extension Array where Element == HTTPHeader {
  335 + /// Case-insensitively finds the index of an `HTTPHeader` with the provided name, if it exists.
  336 + func index(of name: String) -> Int? {
  337 + let lowercasedName = name.lowercased()
  338 + return firstIndex { $0.name.lowercased() == lowercasedName }
  339 + }
  340 +}
  341 +
  342 +// MARK: - Defaults
  343 +
  344 +extension HTTPHeaders {
  345 + /// The default set of `HTTPHeaders` used by Alamofire. Includes `Accept-Encoding`, `Accept-Language`, and
  346 + /// `User-Agent`.
  347 + public static let `default`: HTTPHeaders = [.defaultAcceptEncoding,
  348 + .defaultAcceptLanguage,
  349 + .defaultUserAgent]
  350 +}
  351 +
  352 +extension HTTPHeader {
  353 + /// Returns Alamofire's default `Accept-Encoding` header, appropriate for the encodings supported by particular OS
  354 + /// versions.
  355 + ///
  356 + /// See the [Accept-Encoding HTTP header documentation](https://tools.ietf.org/html/rfc7230#section-4.2.3) .
  357 + public static let defaultAcceptEncoding: HTTPHeader = {
  358 + let encodings: [String]
  359 + if #available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, *) {
  360 + encodings = ["br", "gzip", "deflate"]
  361 + } else {
  362 + encodings = ["gzip", "deflate"]
  363 + }
  364 +
  365 + return .acceptEncoding(encodings.qualityEncoded())
  366 + }()
  367 +
  368 + /// Returns Alamofire's default `Accept-Language` header, generated by querying `Locale` for the user's
  369 + /// `preferredLanguages`.
  370 + ///
  371 + /// See the [Accept-Language HTTP header documentation](https://tools.ietf.org/html/rfc7231#section-5.3.5).
  372 + public static let defaultAcceptLanguage: HTTPHeader = .acceptLanguage(Locale.preferredLanguages.prefix(6).qualityEncoded())
  373 +
  374 + /// Returns Alamofire's default `User-Agent` header.
  375 + ///
  376 + /// See the [User-Agent header documentation](https://tools.ietf.org/html/rfc7231#section-5.5.3).
  377 + ///
  378 + /// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 13.0.0) Alamofire/5.0.0`
  379 + public static let defaultUserAgent: HTTPHeader = {
  380 + let info = Bundle.main.infoDictionary
  381 + let executable = (info?["CFBundleExecutable"] as? String) ??
  382 + (ProcessInfo.processInfo.arguments.first?.split(separator: "/").last.map(String.init)) ??
  383 + "Unknown"
  384 + let bundle = info?["CFBundleIdentifier"] as? String ?? "Unknown"
  385 + let appVersion = info?["CFBundleShortVersionString"] as? String ?? "Unknown"
  386 + let appBuild = info?["CFBundleVersion"] as? String ?? "Unknown"
  387 +
  388 + let osNameVersion: String = {
  389 + let version = ProcessInfo.processInfo.operatingSystemVersion
  390 + let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
  391 + let osName: String = {
  392 + #if os(iOS)
  393 + #if targetEnvironment(macCatalyst)
  394 + return "macOS(Catalyst)"
  395 + #else
  396 + return "iOS"
  397 + #endif
  398 + #elseif os(watchOS)
  399 + return "watchOS"
  400 + #elseif os(tvOS)
  401 + return "tvOS"
  402 + #elseif os(macOS)
  403 + return "macOS"
  404 + #elseif os(Linux)
  405 + return "Linux"
  406 + #elseif os(Windows)
  407 + return "Windows"
  408 + #else
  409 + return "Unknown"
  410 + #endif
  411 + }()
  412 +
  413 + return "\(osName) \(versionString)"
  414 + }()
  415 +
  416 + let alamofireVersion = "Alamofire/\(version)"
  417 +
  418 + let userAgent = "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
  419 +
  420 + return .userAgent(userAgent)
  421 + }()
  422 +}
  423 +
  424 +extension Collection where Element == String {
  425 + func qualityEncoded() -> String {
  426 + enumerated().map { index, encoding in
  427 + let quality = 1.0 - (Double(index) * 0.1)
  428 + return "\(encoding);q=\(quality)"
  429 + }.joined(separator: ", ")
  430 + }
  431 +}
  432 +
  433 +// MARK: - System Type Extensions
  434 +
  435 +extension URLRequest {
  436 + /// Returns `allHTTPHeaderFields` as `HTTPHeaders`.
  437 + public var headers: HTTPHeaders {
  438 + get { allHTTPHeaderFields.map(HTTPHeaders.init) ?? HTTPHeaders() }
  439 + set { allHTTPHeaderFields = newValue.dictionary }
  440 + }
  441 +}
  442 +
  443 +extension HTTPURLResponse {
  444 + /// Returns `allHeaderFields` as `HTTPHeaders`.
  445 + public var headers: HTTPHeaders {
  446 + (allHeaderFields as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders()
  447 + }
  448 +}
  449 +
  450 +extension URLSessionConfiguration {
  451 + /// Returns `httpAdditionalHeaders` as `HTTPHeaders`.
  452 + public var headers: HTTPHeaders {
  453 + get { (httpAdditionalHeaders as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders() }
  454 + set { httpAdditionalHeaders = newValue.dictionary }
  455 + }
  456 +}
Pods/Alamofire/Source/HTTPMethod.swift 0 → 100644
  1 +++ a/Pods/Alamofire/Source/HTTPMethod.swift
  1 +//
  2 +// HTTPMethod.swift
  3 +//
  4 +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5 +//
  6 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  7 +// of this software and associated documentation files (the "Software"), to deal
  8 +// in the Software without restriction, including without limitation the rights
  9 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 +// copies of the Software, and to permit persons to whom the Software is
  11 +// furnished to do so, subject to the following conditions:
  12 +//
  13 +// The above copyright notice and this permission notice shall be included in
  14 +// all copies or substantial portions of the Software.
  15 +//
  16 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 +// THE SOFTWARE.
  23 +//
  24 +
  25 +/// Type representing HTTP methods. Raw `String` value is stored and compared case-sensitively, so
  26 +/// `HTTPMethod.get != HTTPMethod(rawValue: "get")`.
  27 +///
  28 +/// See https://tools.ietf.org/html/rfc7231#section-4.3
  29 +public struct HTTPMethod: RawRepresentable, Equatable, Hashable {
  30 + /// `CONNECT` method.
  31 + public static let connect = HTTPMethod(rawValue: "CONNECT")
  32 + /// `DELETE` method.
  33 + public static let delete = HTTPMethod(rawValue: "DELETE")
  34 + /// `GET` method.
  35 + public static let get = HTTPMethod(rawValue: "GET")
  36 + /// `HEAD` method.
  37 + public static let head = HTTPMethod(rawValue: "HEAD")
  38 + /// `OPTIONS` method.
  39 + public static let options = HTTPMethod(rawValue: "OPTIONS")
  40 + /// `PATCH` method.
  41 + public static let patch = HTTPMethod(rawValue: "PATCH")
  42 + /// `POST` method.
  43 + public static let post = HTTPMethod(rawValue: "POST")
  44 + /// `PUT` method.
  45 + public static let put = HTTPMethod(rawValue: "PUT")
  46 + /// `QUERY` method.
  47 + public static let query = HTTPMethod(rawValue: "QUERY")
  48 + /// `TRACE` method.
  49 + public static let trace = HTTPMethod(rawValue: "TRACE")
  50 +
  51 + public let rawValue: String
  52 +
  53 + public init(rawValue: String) {
  54 + self.rawValue = rawValue
  55 + }
  56 +}