Commit 6f75ef0748a6fe6583f206ac89340b213d69d219
1 parent
78dc198e
ignore something
Showing
14 changed files
with
0 additions
and
4550 deletions
Too many changes to show.
To preserve performance only 14 of 99 files are displayed.
Podfile.lock deleted
100644 → 0
| 1 | -PODS: | ||
| 2 | - - Alamofire (5.7.1) | ||
| 3 | - - Moya (15.0.0): | ||
| 4 | - - Moya/Core (= 15.0.0) | ||
| 5 | - - Moya/Core (15.0.0): | ||
| 6 | - - Alamofire (~> 5.0) | ||
| 7 | - | ||
| 8 | -DEPENDENCIES: | ||
| 9 | - - Alamofire | ||
| 10 | - - Moya | ||
| 11 | - | ||
| 12 | -SPEC REPOS: | ||
| 13 | - trunk: | ||
| 14 | - - Alamofire | ||
| 15 | - - Moya | ||
| 16 | - | ||
| 17 | -SPEC CHECKSUMS: | ||
| 18 | - Alamofire: 0123a34370cb170936ae79a8df46cc62b2edeb88 | ||
| 19 | - Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee | ||
| 20 | - | ||
| 21 | -PODFILE CHECKSUM: 442c78584a02fcf1354da6ef1b93ca3e5ce4fae6 | ||
| 22 | - | ||
| 23 | -COCOAPODS: 1.11.2 |
Pods/Alamofire/LICENSE deleted
100644 → 0
| 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 deleted
100644 → 0
| 1 | - | ||
| 2 | - | ||
| 3 | -[](https://img.shields.io/badge/Swift-5.5_5.6_5.7_5.8-Orange?style=flat-square) | ||
| 4 | -[](https://img.shields.io/badge/Platforms-macOS_iOS_tvOS_watchOS_Linux_Windows-Green?style=flat-square) | ||
| 5 | -[](https://img.shields.io/cocoapods/v/Alamofire.svg) | ||
| 6 | -[](https://github.com/Carthage/Carthage) | ||
| 7 | -[](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square) | ||
| 8 | -[](https://twitter.com/AlamofireSF) | ||
| 9 | -[](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 | - | ||
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 deleted
100644 → 0
| 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 | -} |