Browse Source

Parte de Stephanie, tenia problemas subiendo

Kendrick Morales 5 years ago
parent
commit
2b71d2634c
73 changed files with 13585 additions and 26 deletions
  1. BIN
      .DS_Store
  2. 10
    0
      Podfile
  3. 16
    0
      Podfile.lock
  4. 19
    0
      Pods/Alamofire/LICENSE
  5. 202
    0
      Pods/Alamofire/README.md
  6. 840
    0
      Pods/Alamofire/Source/AFError.swift
  7. 520
    0
      Pods/Alamofire/Source/Alamofire.swift
  8. 58
    0
      Pods/Alamofire/Source/AlamofireExtended.swift
  9. 91
    0
      Pods/Alamofire/Source/CachedResponseHandler.swift
  10. 37
    0
      Pods/Alamofire/Source/DispatchQueue+Alamofire.swift
  11. 844
    0
      Pods/Alamofire/Source/EventMonitor.swift
  12. 445
    0
      Pods/Alamofire/Source/HTTPHeaders.swift
  13. 54
    0
      Pods/Alamofire/Source/HTTPMethod.swift
  14. 544
    0
      Pods/Alamofire/Source/MultipartFormData.swift
  15. 87
    0
      Pods/Alamofire/Source/MultipartUpload.swift
  16. 266
    0
      Pods/Alamofire/Source/NetworkReachabilityManager.swift
  17. 115
    0
      Pods/Alamofire/Source/Notifications.swift
  18. 49
    0
      Pods/Alamofire/Source/OperationQueue+Alamofire.swift
  19. 184
    0
      Pods/Alamofire/Source/ParameterEncoder.swift
  20. 314
    0
      Pods/Alamofire/Source/ParameterEncoding.swift
  21. 167
    0
      Pods/Alamofire/Source/Protector.swift
  22. 95
    0
      Pods/Alamofire/Source/RedirectHandler.swift
  23. 1461
    0
      Pods/Alamofire/Source/Request.swift
  24. 243
    0
      Pods/Alamofire/Source/RequestInterceptor.swift
  25. 136
    0
      Pods/Alamofire/Source/RequestTaskMap.swift
  26. 399
    0
      Pods/Alamofire/Source/Response.swift
  27. 779
    0
      Pods/Alamofire/Source/ResponseSerialization.swift
  28. 109
    0
      Pods/Alamofire/Source/Result+Alamofire.swift
  29. 363
    0
      Pods/Alamofire/Source/RetryPolicy.swift
  30. 606
    0
      Pods/Alamofire/Source/ServerTrustEvaluation.swift
  31. 1039
    0
      Pods/Alamofire/Source/Session.swift
  32. 305
    0
      Pods/Alamofire/Source/SessionDelegate.swift
  33. 105
    0
      Pods/Alamofire/Source/URLConvertible+URLRequestConvertible.swift
  34. 973
    0
      Pods/Alamofire/Source/URLEncodedFormEncoder.swift
  35. 39
    0
      Pods/Alamofire/Source/URLRequest+Alamofire.swift
  36. 37
    0
      Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift
  37. 247
    0
      Pods/Alamofire/Source/Validation.swift
  38. 16
    0
      Pods/Manifest.lock
  39. 734
    0
      Pods/Pods.xcodeproj/project.pbxproj
  40. 60
    0
      Pods/Pods.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/Alamofire.xcscheme
  41. 58
    0
      Pods/Pods.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/Pods-Trolley App.xcscheme
  42. 25
    0
      Pods/Pods.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/xcschememanagement.plist
  43. 26
    0
      Pods/Target Support Files/Alamofire/Alamofire-Info.plist
  44. 5
    0
      Pods/Target Support Files/Alamofire/Alamofire-dummy.m
  45. 12
    0
      Pods/Target Support Files/Alamofire/Alamofire-prefix.pch
  46. 16
    0
      Pods/Target Support Files/Alamofire/Alamofire-umbrella.h
  47. 6
    0
      Pods/Target Support Files/Alamofire/Alamofire.modulemap
  48. 11
    0
      Pods/Target Support Files/Alamofire/Alamofire.xcconfig
  49. 26
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist
  50. 26
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.markdown
  51. 58
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.plist
  52. 5
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-dummy.m
  53. 2
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-input-files.xcfilelist
  54. 1
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-output-files.xcfilelist
  55. 2
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-input-files.xcfilelist
  56. 1
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-output-files.xcfilelist
  57. 171
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh
  58. 16
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-umbrella.h
  59. 12
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.debug.xcconfig
  60. 6
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap
  61. 12
    0
      Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.release.xcconfig
  62. 199
    0
      Trolley App.xcodeproj/project.pbxproj
  63. BIN
      Trolley App.xcodeproj/project.xcworkspace/xcuserdata/kendrickmorales.xcuserdatad/UserInterfaceState.xcuserstate
  64. BIN
      Trolley App.xcodeproj/project.xcworkspace/xcuserdata/stephaniem.ramos.xcuserdatad/UserInterfaceState.xcuserstate
  65. 1
    1
      Trolley App.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/xcschememanagement.plist
  66. 14
    0
      Trolley App.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/xcschememanagement.plist
  67. 10
    0
      Trolley App.xcworkspace/contents.xcworkspacedata
  68. 8
    0
      Trolley App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  69. BIN
      Trolley App.xcworkspace/xcuserdata/kendrickmorales.xcuserdatad/UserInterfaceState.xcuserstate
  70. BIN
      Trolley App/.DS_Store
  71. BIN
      Trolley App/Assets.xcassets/.DS_Store
  72. 220
    18
      Trolley App/Base.lproj/Main.storyboard
  73. 28
    7
      Trolley App/ViewController.swift

BIN
.DS_Store View File


+ 10
- 0
Podfile View File

@@ -0,0 +1,10 @@
1
+# Uncomment the next line to define a global platform for your project
2
+# platform :ios, '9.0'
3
+
4
+target 'Trolley App' do
5
+  # Comment the next line if you don't want to use dynamic frameworks
6
+  use_frameworks!
7
+
8
+  # Pods for Trolley App
9
+  pod 'Alamofire', '~> 5.0.0-rc.3'
10
+end

+ 16
- 0
Podfile.lock View File

@@ -0,0 +1,16 @@
1
+PODS:
2
+  - Alamofire (5.0.0-rc.3)
3
+
4
+DEPENDENCIES:
5
+  - Alamofire (~> 5.0.0-rc.3)
6
+
7
+SPEC REPOS:
8
+  trunk:
9
+    - Alamofire
10
+
11
+SPEC CHECKSUMS:
12
+  Alamofire: ca8c0de6906873be89d6deec5c8de279e00bf872
13
+
14
+PODFILE CHECKSUM: b48a804833d51d78b77457abd4dc6c8ce3d106a2
15
+
16
+COCOAPODS: 1.8.4

+ 19
- 0
Pods/Alamofire/LICENSE View File

@@ -0,0 +1,19 @@
1
+Copyright (c) 2014-2018 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.

+ 202
- 0
Pods/Alamofire/README.md View File

@@ -0,0 +1,202 @@
1
+![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/master/alamofire.png)
2
+
3
+[![Build Status](https://travis-ci.org/Alamofire/Alamofire.svg?branch=master)](https://travis-ci.org/Alamofire/Alamofire)
4
+[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Alamofire.svg)](https://img.shields.io/cocoapods/v/Alamofire.svg)
5
+[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
6
+[![Platform](https://img.shields.io/cocoapods/p/Alamofire.svg?style=flat)](https://alamofire.github.io/Alamofire)
7
+[![Twitter](https://img.shields.io/badge/twitter-@AlamofireSF-blue.svg?style=flat)](https://twitter.com/AlamofireSF)
8
+[![Gitter](https://badges.gitter.im/Alamofire/Alamofire.svg)](https://gitter.im/Alamofire/Alamofire?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
9
+[![Open Source Helpers](https://www.codetriage.com/alamofire/alamofire/badges/users.svg)](https://www.codetriage.com/alamofire/alamofire)
10
+
11
+Alamofire is an HTTP networking library written in Swift.
12
+
13
+**⚠️⚠️⚠️ WARNING ⚠️⚠️⚠️** This documentation is out of date during the Alamofire 5 beta process.
14
+
15
+- [Features](#features)
16
+- [Component Libraries](#component-libraries)
17
+- [Requirements](#requirements)
18
+- [Migration Guides](#migration-guides)
19
+- [Communication](#communication)
20
+- [Installation](#installation)
21
+- [Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#using-alamofire)
22
+    - [**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)
23
+	- **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)
24
+	- **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)
25
+	- **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)
26
+- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md)
27
+	- **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-manager), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-delegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request)
28
+	- **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)
29
+	- **Model Objects -** [Custom Response Serialization](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#custom-response-serialization)
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] URL / JSON / plist Parameter Encoding
41
+- [x] Upload File / Data / Stream / MultipartFormData
42
+- [x] Download File using Request or Resume Data
43
+- [x] Authentication with URLCredential
44
+- [x] HTTP Response Validation
45
+- [x] Upload and Download Progress Closures with Progress
46
+- [x] cURL Command Output
47
+- [x] Dynamically Adapt and Retry Requests
48
+- [x] TLS Certificate and Public Key Pinning
49
+- [x] Network Reachability
50
+- [x] Comprehensive Unit and Integration Test Coverage
51
+- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
52
+
53
+## Component Libraries
54
+
55
+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.
56
+
57
+- [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.
58
+- [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.
59
+
60
+## Requirements
61
+
62
+- iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
63
+- Xcode 10.2+
64
+- Swift 5+
65
+
66
+## Migration Guides
67
+
68
+- Alamofire 5.0 Migration Guide: To be written!
69
+- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md)
70
+- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md)
71
+- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
72
+
73
+## Communication
74
+- If you **need help with making network requests** using Alamofire, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`.
75
+- 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.
76
+- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
77
+- If you'd like to **discuss Alamofire best practices**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
78
+- If you'd like to **discuss a feature request**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire). 
79
+- If you **found a bug**, open an issue here on GitHub and follow the guide. The more detail the better!
80
+- If you **want to contribute**, submit a pull request.
81
+
82
+## Installation
83
+
84
+### CocoaPods
85
+
86
+[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`:
87
+
88
+```ruby
89
+pod 'Alamofire', '~> 5.0.0-rc.3'
90
+```
91
+
92
+### Carthage
93
+
94
+[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`:
95
+
96
+```ogdl
97
+github "Alamofire/Alamofire" "5.0.0-rc.3"
98
+```
99
+
100
+### Swift Package Manager
101
+
102
+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. It is in early development, but Alamofire does support its use on supported platforms.
103
+
104
+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`.
105
+
106
+```swift
107
+dependencies: [
108
+    .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.0.0-rc.3")
109
+]
110
+```
111
+
112
+### Manually
113
+
114
+If you prefer not to use any of the aforementioned dependency managers, you can integrate Alamofire into your project manually.
115
+
116
+#### Embedded Framework
117
+
118
+- 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:
119
+
120
+  ```bash
121
+  $ git init
122
+  ```
123
+
124
+- Add Alamofire as a git [submodule](https://git-scm.com/docs/git-submodule) by running the following command:
125
+
126
+  ```bash
127
+  $ git submodule add https://github.com/Alamofire/Alamofire.git
128
+  ```
129
+
130
+- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project.
131
+
132
+    > 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.
133
+
134
+- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.
135
+- 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.
136
+- In the tab bar at the top of that window, open the "General" panel.
137
+- Click on the `+` button under the "Embedded Binaries" section.
138
+- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder.
139
+
140
+    > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`.
141
+
142
+- Select the top `Alamofire.framework` for iOS and the bottom one for macOS.
143
+
144
+    > You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as either `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS` or `Alamofire watchOS`.
145
+
146
+- And that's it!
147
+
148
+  > 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.
149
+
150
+## Open Radars
151
+
152
+The following radars have some effect on the current implementation of Alamofire.
153
+
154
+- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in test case
155
+- `rdar://26870455` - Background URL Session Configurations do not work in the simulator
156
+- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest`
157
+
158
+## Resolved Radars
159
+
160
+The following radars have been resolved over time after being filed against the Alamofire project.
161
+
162
+- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage.
163
+  - (Resolved): 9/1/17 in Xcode 9 beta 6.
164
+- [`rdar://36082113`](http://openradar.appspot.com/radar?id=4942308441063424) - `URLSessionTaskMetrics` failing to link on watchOS 3.0+
165
+  - (Resolved): Just add `CFNetwork` to your linked frameworks.
166
+  
167
+## FAQ
168
+
169
+### What's the origin of the name Alamofire?
170
+
171
+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.
172
+
173
+## Credits
174
+
175
+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.
176
+
177
+### Security Disclosure
178
+
179
+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.
180
+
181
+## Donations
182
+
183
+The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization.
184
+Registering will allow us members to gain some legal protections and also allow us to put donations to use, tax free.
185
+Donating to the ASF will enable us to:
186
+
187
+- Pay our yearly legal fees to keep the non-profit in good status
188
+- Pay for our mail servers to help us stay on top of all questions and security issues
189
+- Potentially fund test servers to make it easier for us to test the edge cases
190
+- Potentially fund developers to work on one of our projects full-time
191
+
192
+The community adoption of the ASF libraries has been amazing.
193
+We are greatly humbled by your enthusiasm around the projects, and want to continue to do everything we can to move the needle forward.
194
+With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members.
195
+If you use any of our libraries for work, see if your employers would be interested in donating.
196
+Any amount you can donate today to help us reach our goal would be greatly appreciated.
197
+
198
+[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W34WPEE74APJQ)
199
+
200
+## License
201
+
202
+Alamofire is released under the MIT license. [See LICENSE](https://github.com/Alamofire/Alamofire/blob/master/LICENSE) for details.

+ 840
- 0
Pods/Alamofire/Source/AFError.swift View File

@@ -0,0 +1,840 @@
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
+    /// The underlying reason the `.parameterEncodingFailed` error occurred.
61
+    public enum ParameterEncodingFailureReason {
62
+        /// The `URLRequest` did not have a `URL` to encode.
63
+        case missingURL
64
+        /// JSON serialization failed with an underlying system error during the encoding process.
65
+        case jsonEncodingFailed(error: Error)
66
+        /// Custom parameter encoding failed due to the associated `Error`.
67
+        case customEncodingFailed(error: Error)
68
+    }
69
+
70
+    /// The underlying reason the `.parameterEncoderFailed` error occurred.
71
+    public enum ParameterEncoderFailureReason {
72
+        /// Possible missing components.
73
+        public enum RequiredComponent {
74
+            /// The `URL` was missing or unable to be extracted from the passed `URLRequest` or during encoding.
75
+            case url
76
+            /// The `HTTPMethod` could not be extracted from the passed `URLRequest`.
77
+            case httpMethod(rawValue: String)
78
+        }
79
+
80
+        /// A `RequiredComponent` was missing during encoding.
81
+        case missingRequiredComponent(RequiredComponent)
82
+        /// The underlying encoder failed with the associated error.
83
+        case encoderFailed(error: Error)
84
+    }
85
+
86
+    /// The underlying reason the `.responseValidationFailed` error occurred.
87
+    public enum ResponseValidationFailureReason {
88
+        /// The data file containing the server response did not exist.
89
+        case dataFileNil
90
+        /// The data file containing the server response at the associated `URL` could not be read.
91
+        case dataFileReadFailed(at: URL)
92
+        /// The response did not contain a `Content-Type` and the `acceptableContentTypes` provided did not contain a
93
+        /// wildcard type.
94
+        case missingContentType(acceptableContentTypes: [String])
95
+        /// The response `Content-Type` did not match any type in the provided `acceptableContentTypes`.
96
+        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
97
+        /// The response status code was not acceptable.
98
+        case unacceptableStatusCode(code: Int)
99
+        /// Custom response validation failed due to the associated `Error`.
100
+        case customValidationFailed(error: Error)
101
+    }
102
+
103
+    /// The underlying reason the response serialization error occurred.
104
+    public enum ResponseSerializationFailureReason {
105
+        /// The server response contained no data or the data was zero length.
106
+        case inputDataNilOrZeroLength
107
+        /// The file containing the server response did not exist.
108
+        case inputFileNil
109
+        /// The file containing the server response could not be read from the associated `URL`.
110
+        case inputFileReadFailed(at: URL)
111
+        /// String serialization failed using the provided `String.Encoding`.
112
+        case stringSerializationFailed(encoding: String.Encoding)
113
+        /// JSON serialization failed with an underlying system error.
114
+        case jsonSerializationFailed(error: Error)
115
+        /// A `DataDecoder` failed to decode the response due to the associated `Error`.
116
+        case decodingFailed(error: Error)
117
+        /// A custom response serializer failed due to the associated `Error`.
118
+        case customSerializationFailed(error: Error)
119
+        /// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
120
+        case invalidEmptyResponse(type: String)
121
+    }
122
+
123
+    /// Underlying reason a server trust evaluation error occurred.
124
+    public enum ServerTrustFailureReason {
125
+        /// The output of a server trust evaluation.
126
+        public struct Output {
127
+            /// The host for which the evaluation was performed.
128
+            public let host: String
129
+            /// The `SecTrust` value which was evaluated.
130
+            public let trust: SecTrust
131
+            /// The `OSStatus` of evaluation operation.
132
+            public let status: OSStatus
133
+            /// The result of the evaluation operation.
134
+            public let result: SecTrustResultType
135
+
136
+            /// Creates an `Output` value from the provided values.
137
+            init(_ host: String, _ trust: SecTrust, _ status: OSStatus, _ result: SecTrustResultType) {
138
+                self.host = host
139
+                self.trust = trust
140
+                self.status = status
141
+                self.result = result
142
+            }
143
+        }
144
+
145
+        /// No `ServerTrustEvaluator` was found for the associated host.
146
+        case noRequiredEvaluator(host: String)
147
+        /// No certificates were found with which to perform the trust evaluation.
148
+        case noCertificatesFound
149
+        /// No public keys were found with which to perform the trust evaluation.
150
+        case noPublicKeysFound
151
+        /// During evaluation, application of the associated `SecPolicy` failed.
152
+        case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
153
+        /// During evaluation, setting the associated anchor certificates failed.
154
+        case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
155
+        /// During evaluation, creation of the revocation policy failed.
156
+        case revocationPolicyCreationFailed
157
+        /// `SecTrust` evaluation failed with the associated `Error`, if one was produced.
158
+        case trustEvaluationFailed(error: Error?)
159
+        /// Default evaluation failed with the associated `Output`.
160
+        case defaultEvaluationFailed(output: Output)
161
+        /// Host validation failed with the associated `Output`.
162
+        case hostValidationFailed(output: Output)
163
+        /// Revocation check failed with the associated `Output` and options.
164
+        case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
165
+        /// Certificate pinning failed.
166
+        case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
167
+        /// Public key pinning failed.
168
+        case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
169
+        /// Custom server trust evaluation failed due to the associated `Error`.
170
+        case customEvaluationFailed(error: Error)
171
+    }
172
+
173
+    /// The underlying reason the `.urlRequestValidationFailed`
174
+    public enum URLRequestValidationFailureReason {
175
+        /// URLRequest with GET method had body data.
176
+        case bodyDataInGETRequest(Data)
177
+    }
178
+
179
+    ///  `UploadableConvertible` threw an error in `createUploadable()`.
180
+    case createUploadableFailed(error: Error)
181
+    ///  `URLRequestConvertible` threw an error in `asURLRequest()`.
182
+    case createURLRequestFailed(error: Error)
183
+    /// `SessionDelegate` threw an error while attempting to move downloaded file to destination URL.
184
+    case downloadedFileMoveFailed(error: Error, source: URL, destination: URL)
185
+    /// `Request` was explicitly cancelled.
186
+    case explicitlyCancelled
187
+    /// `URLConvertible` type failed to create a valid `URL`.
188
+    case invalidURL(url: URLConvertible)
189
+    /// Multipart form encoding failed.
190
+    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
191
+    /// `ParameterEncoding` threw an error during the encoding process.
192
+    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
193
+    /// `ParameterEncoder` threw an error while running the encoder.
194
+    case parameterEncoderFailed(reason: ParameterEncoderFailureReason)
195
+    /// `RequestAdapter` threw an error during adaptation.
196
+    case requestAdaptationFailed(error: Error)
197
+    /// `RequestRetrier` threw an error during the request retry process.
198
+    case requestRetryFailed(retryError: Error, originalError: Error)
199
+    /// Response validation failed.
200
+    case responseValidationFailed(reason: ResponseValidationFailureReason)
201
+    /// Response serialization failed.
202
+    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
203
+    /// `ServerTrustEvaluating` instance threw an error during trust evaluation.
204
+    case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
205
+    /// `Session` which issued the `Request` was deinitialized, most likely because its reference went out of scope.
206
+    case sessionDeinitialized
207
+    /// `Session` was explicitly invalidated, possibly with the `Error` produced by the underlying `URLSession`.
208
+    case sessionInvalidated(error: Error?)
209
+    /// `URLSessionTask` completed with error.
210
+    case sessionTaskFailed(error: Error)
211
+    /// `URLRequest` failed validation.
212
+    case urlRequestValidationFailed(reason: URLRequestValidationFailureReason)
213
+}
214
+
215
+extension Error {
216
+    /// Returns the instance cast as an `AFError`.
217
+    public var asAFError: AFError? {
218
+        return self as? AFError
219
+    }
220
+
221
+    /// Returns the instance cast as an `AFError`. If casting fails, a `fatalError` with the specified `message` is thrown.
222
+    public func asAFError(orFailWith message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) -> AFError {
223
+        guard let afError = self as? AFError else {
224
+            fatalError(message(), file: file, line: line)
225
+        }
226
+        return afError
227
+    }
228
+
229
+    /// Casts the instance as `AFError` or returns `defaultAFError`
230
+    func asAFError(or defaultAFError: @autoclosure () -> AFError) -> AFError {
231
+        return self as? AFError ?? defaultAFError()
232
+    }
233
+}
234
+
235
+// MARK: - Error Booleans
236
+
237
+extension AFError {
238
+    /// Returns whether the instance is `.sessionDeinitialized`.
239
+    public var isSessionDeinitializedError: Bool {
240
+        if case .sessionDeinitialized = self { return true }
241
+        return false
242
+    }
243
+
244
+    /// Returns whether the instance is `.sessionInvalidated`.
245
+    public var isSessionInvalidatedError: Bool {
246
+        if case .sessionInvalidated = self { return true }
247
+        return false
248
+    }
249
+
250
+    /// Returns whether the instance is `.explicitlyCancelled`.
251
+    public var isExplicitlyCancelledError: Bool {
252
+        if case .explicitlyCancelled = self { return true }
253
+        return false
254
+    }
255
+
256
+    /// Returns whether the instance is `.invalidURL`.
257
+    public var isInvalidURLError: Bool {
258
+        if case .invalidURL = self { return true }
259
+        return false
260
+    }
261
+
262
+    /// Returns whether the instance is `.parameterEncodingFailed`. When `true`, the `underlyingError` property will
263
+    /// contain the associated value.
264
+    public var isParameterEncodingError: Bool {
265
+        if case .parameterEncodingFailed = self { return true }
266
+        return false
267
+    }
268
+
269
+    /// Returns whether the instance is `.parameterEncoderFailed`. When `true`, the `underlyingError` property will
270
+    /// contain the associated value.
271
+    public var isParameterEncoderError: Bool {
272
+        if case .parameterEncoderFailed = self { return true }
273
+        return false
274
+    }
275
+
276
+    /// Returns whether the instance is `.multipartEncodingFailed`. When `true`, the `url` and `underlyingError`
277
+    /// properties will contain the associated values.
278
+    public var isMultipartEncodingError: Bool {
279
+        if case .multipartEncodingFailed = self { return true }
280
+        return false
281
+    }
282
+
283
+    /// Returns whether the instance is `.requestAdaptationFailed`. When `true`, the `underlyingError` property will
284
+    /// contain the associated value.
285
+    public var isRequestAdaptationError: Bool {
286
+        if case .requestAdaptationFailed = self { return true }
287
+        return false
288
+    }
289
+
290
+    /// Returns whether the instance is `.responseValidationFailed`. When `true`, the `acceptableContentTypes`,
291
+    /// `responseContentType`,  `responseCode`, and `underlyingError` properties will contain the associated values.
292
+    public var isResponseValidationError: Bool {
293
+        if case .responseValidationFailed = self { return true }
294
+        return false
295
+    }
296
+
297
+    /// Returns whether the instance is `.responseSerializationFailed`. When `true`, the `failedStringEncoding` and
298
+    /// `underlyingError` properties will contain the associated values.
299
+    public var isResponseSerializationError: Bool {
300
+        if case .responseSerializationFailed = self { return true }
301
+        return false
302
+    }
303
+
304
+    /// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
305
+    /// contain the associated value.
306
+    public var isServerTrustEvaluationError: Bool {
307
+        if case .serverTrustEvaluationFailed = self { return true }
308
+        return false
309
+    }
310
+
311
+    /// Returns whether the instance is `requestRetryFailed`. When `true`, the `underlyingError` property will
312
+    /// contain the associated value.
313
+    public var isRequestRetryError: Bool {
314
+        if case .requestRetryFailed = self { return true }
315
+        return false
316
+    }
317
+
318
+    /// Returns whether the instance is `createUploadableFailed`. When `true`, the `underlyingError` property will
319
+    /// contain the associated value.
320
+    public var isCreateUploadableError: Bool {
321
+        if case .createUploadableFailed = self { return true }
322
+        return false
323
+    }
324
+
325
+    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
326
+    /// contain the associated value.
327
+    public var isCreateURLRequestError: Bool {
328
+        if case .createURLRequestFailed = self { return true }
329
+        return false
330
+    }
331
+
332
+    /// Returns whether the instance is `downloadedFileMoveFailed`. When `true`, the `destination` and `underlyingError` properties will
333
+    /// contain the associated values.
334
+    public var isDownloadedFileMoveError: Bool {
335
+        if case .downloadedFileMoveFailed = self { return true }
336
+        return false
337
+    }
338
+
339
+    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
340
+    /// contain the associated value.
341
+    public var isSessionTaskError: Bool {
342
+        if case .sessionTaskFailed = self { return true }
343
+        return false
344
+    }
345
+}
346
+
347
+// MARK: - Convenience Properties
348
+
349
+extension AFError {
350
+    /// The `URLConvertible` associated with the error.
351
+    public var urlConvertible: URLConvertible? {
352
+        guard case let .invalidURL(url) = self else { return nil }
353
+        return url
354
+    }
355
+
356
+    /// The `URL` associated with the error.
357
+    public var url: URL? {
358
+        guard case let .multipartEncodingFailed(reason) = self else { return nil }
359
+        return reason.url
360
+    }
361
+
362
+    /// The underlying `Error` responsible for generating the failure associated with `.sessionInvalidated`,
363
+    /// `.parameterEncodingFailed`, `.parameterEncoderFailed`, `.multipartEncodingFailed`, `.requestAdaptationFailed`,
364
+    /// `.responseSerializationFailed`, `.requestRetryFailed` errors.
365
+    public var underlyingError: Error? {
366
+        switch self {
367
+        case let .multipartEncodingFailed(reason):
368
+            return reason.underlyingError
369
+        case let .parameterEncodingFailed(reason):
370
+            return reason.underlyingError
371
+        case let .parameterEncoderFailed(reason):
372
+            return reason.underlyingError
373
+        case let .requestAdaptationFailed(error):
374
+            return error
375
+        case let .requestRetryFailed(retryError, _):
376
+            return retryError
377
+        case let .responseValidationFailed(reason):
378
+            return reason.underlyingError
379
+        case let .responseSerializationFailed(reason):
380
+            return reason.underlyingError
381
+        case let .serverTrustEvaluationFailed(reason):
382
+            return reason.underlyingError
383
+        case let .sessionInvalidated(error):
384
+            return error
385
+        case let .createUploadableFailed(error):
386
+            return error
387
+        case let .createURLRequestFailed(error):
388
+            return error
389
+        case let .downloadedFileMoveFailed(error, _, _):
390
+            return error
391
+        case let .sessionTaskFailed(error):
392
+            return error
393
+        case .explicitlyCancelled,
394
+             .invalidURL,
395
+             .sessionDeinitialized,
396
+             .urlRequestValidationFailed:
397
+            return nil
398
+        }
399
+    }
400
+
401
+    /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
402
+    public var acceptableContentTypes: [String]? {
403
+        guard case let .responseValidationFailed(reason) = self else { return nil }
404
+        return reason.acceptableContentTypes
405
+    }
406
+
407
+    /// The response `Content-Type` of a `.responseValidationFailed` error.
408
+    public var responseContentType: String? {
409
+        guard case let .responseValidationFailed(reason) = self else { return nil }
410
+        return reason.responseContentType
411
+    }
412
+
413
+    /// The response code of a `.responseValidationFailed` error.
414
+    public var responseCode: Int? {
415
+        guard case let .responseValidationFailed(reason) = self else { return nil }
416
+        return reason.responseCode
417
+    }
418
+
419
+    /// The `String.Encoding` associated with a failed `.stringResponse()` call.
420
+    public var failedStringEncoding: String.Encoding? {
421
+        guard case let .responseSerializationFailed(reason) = self else { return nil }
422
+        return reason.failedStringEncoding
423
+    }
424
+
425
+    /// The `source` URL of a `.downloadedFileMoveFailed` error.
426
+    public var sourceURL: URL? {
427
+        guard case let .downloadedFileMoveFailed(_, source, _) = self else { return nil }
428
+        return source
429
+    }
430
+
431
+    /// The `destination` URL of a `.downloadedFileMoveFailed` error.
432
+    public var destinationURL: URL? {
433
+        guard case let .downloadedFileMoveFailed(_, _, destination) = self else { return nil }
434
+        return destination
435
+    }
436
+}
437
+
438
+extension AFError.ParameterEncodingFailureReason {
439
+    var underlyingError: Error? {
440
+        switch self {
441
+        case let .jsonEncodingFailed(error),
442
+             let .customEncodingFailed(error):
443
+            return error
444
+        case .missingURL:
445
+            return nil
446
+        }
447
+    }
448
+}
449
+
450
+extension AFError.ParameterEncoderFailureReason {
451
+    var underlyingError: Error? {
452
+        switch self {
453
+        case let .encoderFailed(error):
454
+            return error
455
+        case .missingRequiredComponent:
456
+            return nil
457
+        }
458
+    }
459
+}
460
+
461
+extension AFError.MultipartEncodingFailureReason {
462
+    var url: URL? {
463
+        switch self {
464
+        case let .bodyPartURLInvalid(url),
465
+             let .bodyPartFilenameInvalid(url),
466
+             let .bodyPartFileNotReachable(url),
467
+             let .bodyPartFileIsDirectory(url),
468
+             let .bodyPartFileSizeNotAvailable(url),
469
+             let .bodyPartInputStreamCreationFailed(url),
470
+             let .outputStreamCreationFailed(url),
471
+             let .outputStreamFileAlreadyExists(url),
472
+             let .outputStreamURLInvalid(url),
473
+             let .bodyPartFileNotReachableWithError(url, _),
474
+             let .bodyPartFileSizeQueryFailedWithError(url, _):
475
+            return url
476
+        case .outputStreamWriteFailed,
477
+             .inputStreamReadFailed:
478
+            return nil
479
+        }
480
+    }
481
+
482
+    var underlyingError: Error? {
483
+        switch self {
484
+        case let .bodyPartFileNotReachableWithError(_, error),
485
+             let .bodyPartFileSizeQueryFailedWithError(_, error),
486
+             let .outputStreamWriteFailed(error),
487
+             let .inputStreamReadFailed(error):
488
+            return error
489
+        case .bodyPartURLInvalid,
490
+             .bodyPartFilenameInvalid,
491
+             .bodyPartFileNotReachable,
492
+             .bodyPartFileIsDirectory,
493
+             .bodyPartFileSizeNotAvailable,
494
+             .bodyPartInputStreamCreationFailed,
495
+             .outputStreamCreationFailed,
496
+             .outputStreamFileAlreadyExists,
497
+             .outputStreamURLInvalid:
498
+            return nil
499
+        }
500
+    }
501
+}
502
+
503
+extension AFError.ResponseValidationFailureReason {
504
+    var acceptableContentTypes: [String]? {
505
+        switch self {
506
+        case let .missingContentType(types),
507
+             let .unacceptableContentType(types, _):
508
+            return types
509
+        case .dataFileNil,
510
+             .dataFileReadFailed,
511
+             .unacceptableStatusCode,
512
+             .customValidationFailed:
513
+            return nil
514
+        }
515
+    }
516
+
517
+    var responseContentType: String? {
518
+        switch self {
519
+        case let .unacceptableContentType(_, responseType):
520
+            return responseType
521
+        case .dataFileNil,
522
+             .dataFileReadFailed,
523
+             .missingContentType,
524
+             .unacceptableStatusCode,
525
+             .customValidationFailed:
526
+            return nil
527
+        }
528
+    }
529
+
530
+    var responseCode: Int? {
531
+        switch self {
532
+        case let .unacceptableStatusCode(code):
533
+            return code
534
+        case .dataFileNil,
535
+             .dataFileReadFailed,
536
+             .missingContentType,
537
+             .unacceptableContentType,
538
+             .customValidationFailed:
539
+            return nil
540
+        }
541
+    }
542
+
543
+    var underlyingError: Error? {
544
+        switch self {
545
+        case let .customValidationFailed(error):
546
+            return error
547
+        case .dataFileNil,
548
+             .dataFileReadFailed,
549
+             .missingContentType,
550
+             .unacceptableContentType,
551
+             .unacceptableStatusCode:
552
+            return nil
553
+        }
554
+    }
555
+}
556
+
557
+extension AFError.ResponseSerializationFailureReason {
558
+    var failedStringEncoding: String.Encoding? {
559
+        switch self {
560
+        case let .stringSerializationFailed(encoding):
561
+            return encoding
562
+        case .inputDataNilOrZeroLength,
563
+             .inputFileNil,
564
+             .inputFileReadFailed(_),
565
+             .jsonSerializationFailed(_),
566
+             .decodingFailed(_),
567
+             .customSerializationFailed(_),
568
+             .invalidEmptyResponse:
569
+            return nil
570
+        }
571
+    }
572
+
573
+    var underlyingError: Error? {
574
+        switch self {
575
+        case let .jsonSerializationFailed(error),
576
+             let .decodingFailed(error),
577
+             let .customSerializationFailed(error):
578
+            return error
579
+        case .inputDataNilOrZeroLength,
580
+             .inputFileNil,
581
+             .inputFileReadFailed,
582
+             .stringSerializationFailed,
583
+             .invalidEmptyResponse:
584
+            return nil
585
+        }
586
+    }
587
+}
588
+
589
+extension AFError.ServerTrustFailureReason {
590
+    var output: AFError.ServerTrustFailureReason.Output? {
591
+        switch self {
592
+        case let .defaultEvaluationFailed(output),
593
+             let .hostValidationFailed(output),
594
+             let .revocationCheckFailed(output, _):
595
+            return output
596
+        case .noRequiredEvaluator,
597
+             .noCertificatesFound,
598
+             .noPublicKeysFound,
599
+             .policyApplicationFailed,
600
+             .settingAnchorCertificatesFailed,
601
+             .revocationPolicyCreationFailed,
602
+             .trustEvaluationFailed,
603
+             .certificatePinningFailed,
604
+             .publicKeyPinningFailed,
605
+             .customEvaluationFailed:
606
+            return nil
607
+        }
608
+    }
609
+
610
+    var underlyingError: Error? {
611
+        switch self {
612
+        case let .customEvaluationFailed(error):
613
+            return error
614
+        case let .trustEvaluationFailed(error):
615
+            return error
616
+        case .noRequiredEvaluator,
617
+             .noCertificatesFound,
618
+             .noPublicKeysFound,
619
+             .policyApplicationFailed,
620
+             .settingAnchorCertificatesFailed,
621
+             .revocationPolicyCreationFailed,
622
+             .defaultEvaluationFailed,
623
+             .hostValidationFailed,
624
+             .revocationCheckFailed,
625
+             .certificatePinningFailed,
626
+             .publicKeyPinningFailed:
627
+            return nil
628
+        }
629
+    }
630
+}
631
+
632
+// MARK: - Error Descriptions
633
+
634
+extension AFError: LocalizedError {
635
+    public var errorDescription: String? {
636
+        switch self {
637
+        case .explicitlyCancelled:
638
+            return "Request explicitly cancelled."
639
+        case let .invalidURL(url):
640
+            return "URL is not valid: \(url)"
641
+        case let .parameterEncodingFailed(reason):
642
+            return reason.localizedDescription
643
+        case let .parameterEncoderFailed(reason):
644
+            return reason.localizedDescription
645
+        case let .multipartEncodingFailed(reason):
646
+            return reason.localizedDescription
647
+        case let .requestAdaptationFailed(error):
648
+            return "Request adaption failed with error: \(error.localizedDescription)"
649
+        case let .responseValidationFailed(reason):
650
+            return reason.localizedDescription
651
+        case let .responseSerializationFailed(reason):
652
+            return reason.localizedDescription
653
+        case let .requestRetryFailed(retryError, originalError):
654
+            return """
655
+            Request retry failed with retry error: \(retryError.localizedDescription), \
656
+            original error: \(originalError.localizedDescription)
657
+            """
658
+        case .sessionDeinitialized:
659
+            return """
660
+            Session was invalidated without error, so it was likely deinitialized unexpectedly. \
661
+            Be sure to retain a reference to your Session for the duration of your requests.
662
+            """
663
+        case let .sessionInvalidated(error):
664
+            return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
665
+        case let .serverTrustEvaluationFailed(reason):
666
+            return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
667
+        case let .urlRequestValidationFailed(reason):
668
+            return "URLRequest validation failed due to reason: \(reason.localizedDescription)"
669
+        case let .createUploadableFailed(error):
670
+            return "Uploadable creation failed with error: \(error.localizedDescription)"
671
+        case let .createURLRequestFailed(error):
672
+            return "URLRequest creation failed with error: \(error.localizedDescription)"
673
+        case let .downloadedFileMoveFailed(error, source, destination):
674
+            return "Moving downloaded file from: \(source) to: \(destination) failed with error: \(error.localizedDescription)"
675
+        case let .sessionTaskFailed(error):
676
+            return "URLSessionTask failed with error: \(error.localizedDescription)"
677
+        }
678
+    }
679
+}
680
+
681
+extension AFError.ParameterEncodingFailureReason {
682
+    var localizedDescription: String {
683
+        switch self {
684
+        case .missingURL:
685
+            return "URL request to encode was missing a URL"
686
+        case let .jsonEncodingFailed(error):
687
+            return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
688
+        case let .customEncodingFailed(error):
689
+            return "Custom parameter encoder failed with error: \(error.localizedDescription)"
690
+        }
691
+    }
692
+}
693
+
694
+extension AFError.ParameterEncoderFailureReason {
695
+    var localizedDescription: String {
696
+        switch self {
697
+        case let .missingRequiredComponent(component):
698
+            return "Encoding failed due to a missing request component: \(component)"
699
+        case let .encoderFailed(error):
700
+            return "The underlying encoder failed with the error: \(error)"
701
+        }
702
+    }
703
+}
704
+
705
+extension AFError.MultipartEncodingFailureReason {
706
+    var localizedDescription: String {
707
+        switch self {
708
+        case let .bodyPartURLInvalid(url):
709
+            return "The URL provided is not a file URL: \(url)"
710
+        case let .bodyPartFilenameInvalid(url):
711
+            return "The URL provided does not have a valid filename: \(url)"
712
+        case let .bodyPartFileNotReachable(url):
713
+            return "The URL provided is not reachable: \(url)"
714
+        case let .bodyPartFileNotReachableWithError(url, error):
715
+            return """
716
+            The system returned an error while checking the provided URL for reachability.
717
+            URL: \(url)
718
+            Error: \(error)
719
+            """
720
+        case let .bodyPartFileIsDirectory(url):
721
+            return "The URL provided is a directory: \(url)"
722
+        case let .bodyPartFileSizeNotAvailable(url):
723
+            return "Could not fetch the file size from the provided URL: \(url)"
724
+        case let .bodyPartFileSizeQueryFailedWithError(url, error):
725
+            return """
726
+            The system returned an error while attempting to fetch the file size from the provided URL.
727
+            URL: \(url)
728
+            Error: \(error)
729
+            """
730
+        case let .bodyPartInputStreamCreationFailed(url):
731
+            return "Failed to create an InputStream for the provided URL: \(url)"
732
+        case let .outputStreamCreationFailed(url):
733
+            return "Failed to create an OutputStream for URL: \(url)"
734
+        case let .outputStreamFileAlreadyExists(url):
735
+            return "A file already exists at the provided URL: \(url)"
736
+        case let .outputStreamURLInvalid(url):
737
+            return "The provided OutputStream URL is invalid: \(url)"
738
+        case let .outputStreamWriteFailed(error):
739
+            return "OutputStream write failed with error: \(error)"
740
+        case let .inputStreamReadFailed(error):
741
+            return "InputStream read failed with error: \(error)"
742
+        }
743
+    }
744
+}
745
+
746
+extension AFError.ResponseSerializationFailureReason {
747
+    var localizedDescription: String {
748
+        switch self {
749
+        case .inputDataNilOrZeroLength:
750
+            return "Response could not be serialized, input data was nil or zero length."
751
+        case .inputFileNil:
752
+            return "Response could not be serialized, input file was nil."
753
+        case let .inputFileReadFailed(url):
754
+            return "Response could not be serialized, input file could not be read: \(url)."
755
+        case let .stringSerializationFailed(encoding):
756
+            return "String could not be serialized with encoding: \(encoding)."
757
+        case let .jsonSerializationFailed(error):
758
+            return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
759
+        case let .invalidEmptyResponse(type):
760
+            return """
761
+            Empty response could not be serialized to type: \(type). \
762
+            Use Empty as the expected type for such responses.
763
+            """
764
+        case let .decodingFailed(error):
765
+            return "Response could not be decoded because of error:\n\(error.localizedDescription)"
766
+        case let .customSerializationFailed(error):
767
+            return "Custom response serializer failed with error:\n\(error.localizedDescription)"
768
+        }
769
+    }
770
+}
771
+
772
+extension AFError.ResponseValidationFailureReason {
773
+    var localizedDescription: String {
774
+        switch self {
775
+        case .dataFileNil:
776
+            return "Response could not be validated, data file was nil."
777
+        case let .dataFileReadFailed(url):
778
+            return "Response could not be validated, data file could not be read: \(url)."
779
+        case let .missingContentType(types):
780
+            return """
781
+            Response Content-Type was missing and acceptable content types \
782
+            (\(types.joined(separator: ","))) do not match "*/*".
783
+            """
784
+        case let .unacceptableContentType(acceptableTypes, responseType):
785
+            return """
786
+            Response Content-Type "\(responseType)" does not match any acceptable types: \
787
+            \(acceptableTypes.joined(separator: ",")).
788
+            """
789
+        case let .unacceptableStatusCode(code):
790
+            return "Response status code was unacceptable: \(code)."
791
+        case let .customValidationFailed(error):
792
+            return "Custom response validation failed with error: \(error.localizedDescription)"
793
+        }
794
+    }
795
+}
796
+
797
+extension AFError.ServerTrustFailureReason {
798
+    var localizedDescription: String {
799
+        switch self {
800
+        case let .noRequiredEvaluator(host):
801
+            return "A ServerTrustEvaluating value is required for host \(host) but none was found."
802
+        case .noCertificatesFound:
803
+            return "No certificates were found or provided for evaluation."
804
+        case .noPublicKeysFound:
805
+            return "No public keys were found or provided for evaluation."
806
+        case .policyApplicationFailed:
807
+            return "Attempting to set a SecPolicy failed."
808
+        case .settingAnchorCertificatesFailed:
809
+            return "Attempting to set the provided certificates as anchor certificates failed."
810
+        case .revocationPolicyCreationFailed:
811
+            return "Attempting to create a revocation policy failed."
812
+        case let .trustEvaluationFailed(error):
813
+            return "SecTrust evaluation failed with error: \(error?.localizedDescription ?? "None")"
814
+        case let .defaultEvaluationFailed(output):
815
+            return "Default evaluation failed for host \(output.host)."
816
+        case let .hostValidationFailed(output):
817
+            return "Host validation failed for host \(output.host)."
818
+        case let .revocationCheckFailed(output, _):
819
+            return "Revocation check failed for host \(output.host)."
820
+        case let .certificatePinningFailed(host, _, _, _):
821
+            return "Certificate pinning failed for host \(host)."
822
+        case let .publicKeyPinningFailed(host, _, _, _):
823
+            return "Public key pinning failed for host \(host)."
824
+        case let .customEvaluationFailed(error):
825
+            return "Custom trust evaluation failed with error: \(error.localizedDescription)"
826
+        }
827
+    }
828
+}
829
+
830
+extension AFError.URLRequestValidationFailureReason {
831
+    var localizedDescription: String {
832
+        switch self {
833
+        case let .bodyDataInGETRequest(data):
834
+            return """
835
+            Invalid URLRequest: Requests with GET method cannot have body data:
836
+            \(String(decoding: data, as: UTF8.self))
837
+            """
838
+        }
839
+    }
840
+}

+ 520
- 0
Pods/Alamofire/Source/Alamofire.swift View File

@@ -0,0 +1,520 @@
1
+//
2
+//  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 Foundation
26
+
27
+/// Global namespace containing API for the `default` `Session` instance.
28
+public enum AF {
29
+    /// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
30
+    static let version = "5.0.0-rc.3"
31
+
32
+    // MARK: - Data Request
33
+
34
+    /// Creates a `DataRequest` using `Session.default` to retrieve the contents of the specified `url` using the
35
+    /// `method`, `parameters`, `encoding`, and `headers` provided.
36
+    ///
37
+    /// - Parameters:
38
+    ///   - url:           The `URLConvertible` value.
39
+    ///   - method:        The `HTTPMethod`, `.get` by default.
40
+    ///   - parameters:    The `Parameters`, `nil` by default.
41
+    ///   - encoding:      The `ParameterEncoding`, `URLEncoding.default` by default.
42
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
43
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
44
+    ///
45
+    /// - Returns: The created `DataRequest`.
46
+    public static func request(_ url: URLConvertible,
47
+                               method: HTTPMethod = .get,
48
+                               parameters: Parameters? = nil,
49
+                               encoding: ParameterEncoding = URLEncoding.default,
50
+                               headers: HTTPHeaders? = nil,
51
+                               interceptor: RequestInterceptor? = nil) -> DataRequest {
52
+        return Session.default.request(url,
53
+                                       method: method,
54
+                                       parameters: parameters,
55
+                                       encoding: encoding,
56
+                                       headers: headers,
57
+                                       interceptor: interceptor)
58
+    }
59
+
60
+    /// Creates a `DataRequest` using `Session.default` to retrieve the contents of the specified `url` using the
61
+    /// `method`, `parameters`, `encoding`, and `headers` provided.
62
+    ///
63
+    /// - Parameters:
64
+    ///   - url:           The `URLConvertible` value.
65
+    ///   - method:        The `HTTPMethod`, `.get` by default.
66
+    ///   - parameters:    The `Encodable` parameters, `nil` by default.
67
+    ///   - encoding:      The `ParameterEncoder`, `URLEncodedFormParameterEncoder.default` by default.
68
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
69
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
70
+    ///
71
+    /// - Returns: The created `DataRequest`.
72
+    public static func request<Parameters: Encodable>(_ url: URLConvertible,
73
+                                                      method: HTTPMethod = .get,
74
+                                                      parameters: Parameters? = nil,
75
+                                                      encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
76
+                                                      headers: HTTPHeaders? = nil,
77
+                                                      interceptor: RequestInterceptor? = nil) -> DataRequest {
78
+        return Session.default.request(url,
79
+                                       method: method,
80
+                                       parameters: parameters,
81
+                                       encoder: encoder,
82
+                                       headers: headers,
83
+                                       interceptor: interceptor)
84
+    }
85
+
86
+    /// Creates a `DataRequest` using `Session.default` to execute the specified `urlRequest`.
87
+    ///
88
+    /// - Parameters:
89
+    ///   - urlRequest:    The `URLRequestConvertible` value.
90
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
91
+    ///
92
+    /// - Returns: The created `DataRequest`.
93
+    public static func request(_ urlRequest: URLRequestConvertible, interceptor: RequestInterceptor? = nil) -> DataRequest {
94
+        return Session.default.request(urlRequest, interceptor: interceptor)
95
+    }
96
+
97
+    // MARK: - Download Request
98
+
99
+    /// Creates a `DownloadRequest` using `Session.default` to download the contents of the specified `url` to
100
+    /// the provided `destination` using the `method`, `parameters`, `encoding`, and `headers` provided.
101
+    ///
102
+    /// If `destination` is not specified, the download will be moved to a temporary location determined by Alamofire.
103
+    ///
104
+    /// - Parameters:
105
+    ///   - url:           The `URLConvertible` value.
106
+    ///   - method:        The `HTTPMethod`, `.get` by default.
107
+    ///   - parameters:    The `Parameters`, `nil` by default.
108
+    ///   - encoding:      The `ParameterEncoding`, `URLEncoding.default` by default.
109
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
110
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
111
+    ///   - destination:   The `DownloadRequest.Destination` closure used the determine the destination of the
112
+    ///                    downloaded file. `nil` by default.
113
+    ///
114
+    /// - Returns: The created `DownloadRequest`.
115
+    public static func download(_ url: URLConvertible,
116
+                                method: HTTPMethod = .get,
117
+                                parameters: Parameters? = nil,
118
+                                encoding: ParameterEncoding = URLEncoding.default,
119
+                                headers: HTTPHeaders? = nil,
120
+                                interceptor: RequestInterceptor? = nil,
121
+                                to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
122
+        return Session.default.download(url,
123
+                                        method: method,
124
+                                        parameters: parameters,
125
+                                        encoding: encoding,
126
+                                        headers: headers,
127
+                                        interceptor: interceptor,
128
+                                        to: destination)
129
+    }
130
+
131
+    /// Creates a `DownloadRequest` using `Session.default` to download the contents of the specified `url` to the
132
+    /// provided `destination` using the `method`, encodable `parameters`, `encoder`, and `headers` provided.
133
+    ///
134
+    /// - Note: If `destination` is not specified, the download will be moved to a temporary location determined by
135
+    ///         Alamofire.
136
+    ///
137
+    /// - Parameters:
138
+    ///   - url:           The `URLConvertible` value.
139
+    ///   - method:        The `HTTPMethod`, `.get` by default.
140
+    ///   - parameters:    The `Encodable` parameters, `nil` by default.
141
+    ///   - encoder:       The `ParameterEncoder`, `URLEncodedFormParameterEncoder.default` by default.
142
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
143
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
144
+    ///   - destination:   The `DownloadRequest.Destination` closure used the determine the destination of the
145
+    ///                    downloaded file. `nil` by default.
146
+    ///
147
+    /// - Returns: The created `DownloadRequest`.
148
+    public static func download<Parameters: Encodable>(_ url: URLConvertible,
149
+                                                       method: HTTPMethod = .get,
150
+                                                       parameters: Parameters? = nil,
151
+                                                       encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
152
+                                                       headers: HTTPHeaders? = nil,
153
+                                                       interceptor: RequestInterceptor? = nil,
154
+                                                       to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
155
+        return Session.default.download(url,
156
+                                        method: method,
157
+                                        parameters: parameters,
158
+                                        encoder: encoder,
159
+                                        headers: headers,
160
+                                        interceptor: interceptor,
161
+                                        to: destination)
162
+    }
163
+
164
+    // MARK: URLRequest
165
+
166
+    /// Creates a `DownloadRequest` using `Session.default` to execute the specified `urlRequest` and download
167
+    /// the result to the provided `destination`.
168
+    ///
169
+    /// - Parameters:
170
+    ///   - urlRequest:    The `URLRequestConvertible` value.
171
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
172
+    ///   - destination:   The `DownloadRequest.Destination` closure used the determine the destination of the
173
+    ///                    downloaded file. `nil` by default.
174
+    ///
175
+    /// - Returns: The created `DownloadRequest`.
176
+    public static func download(_ urlRequest: URLRequestConvertible,
177
+                                interceptor: RequestInterceptor? = nil,
178
+                                to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
179
+        return Session.default.download(urlRequest, interceptor: interceptor, to: destination)
180
+    }
181
+
182
+    // MARK: Resume Data
183
+
184
+    /// Creates a `DownloadRequest` using the `Session.default` from the `resumeData` produced from a previous
185
+    /// `DownloadRequest` cancellation to retrieve the contents of the original request and save them to the `destination`.
186
+    ///
187
+    /// - Note: If `destination` is not specified, the download will be moved to a temporary location determined by
188
+    ///         Alamofire.
189
+    ///
190
+    /// - Note: On some versions of all Apple platforms (iOS 10 - 10.2, macOS 10.12 - 10.12.2, tvOS 10 - 10.1, watchOS 3 - 3.1.1),
191
+    /// `resumeData` is broken on background URL session configurations. There's an underlying bug in the `resumeData`
192
+    /// generation logic where the data is written incorrectly and will always fail to resume the download. For more
193
+    /// information about the bug and possible workarounds, please refer to the [this Stack Overflow post](http://stackoverflow.com/a/39347461/1342462).
194
+    ///
195
+    /// - Parameters:
196
+    ///   - resumeData:    The resume `Data`. This is an opaque blob produced by `URLSessionDownloadTask` when a task is
197
+    ///                    cancelled. See [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel)
198
+    ///                    for more information.
199
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
200
+    ///   - destination:   The `DownloadRequest.Destination` closure used to determine the destination of the downloaded
201
+    ///                    file. `nil` by default.
202
+    ///
203
+    /// - Returns:         The created `DownloadRequest`.
204
+    public static func download(resumingWith resumeData: Data,
205
+                                interceptor: RequestInterceptor? = nil,
206
+                                to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
207
+        return Session.default.download(resumingWith: resumeData, interceptor: interceptor, to: destination)
208
+    }
209
+
210
+    // MARK: - Upload Request
211
+
212
+    // MARK: Data
213
+
214
+    /// Creates an `UploadRequest` for the given `Data`, `URLRequest` components, and `RequestInterceptor`.
215
+    ///
216
+    /// - Parameters:
217
+    ///   - data:        The `Data` to upload.
218
+    ///   - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
219
+    ///   - method:      `HTTPMethod` for the `URLRequest`. `.post` by default.
220
+    ///   - headers:     `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
221
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
222
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
223
+    ///                  default.
224
+    ///
225
+    /// - Returns:       The created `UploadRequest`.
226
+    public static func upload(_ data: Data,
227
+                              to convertible: URLConvertible,
228
+                              method: HTTPMethod = .post,
229
+                              headers: HTTPHeaders? = nil,
230
+                              interceptor: RequestInterceptor? = nil,
231
+                              fileManager: FileManager = .default) -> UploadRequest {
232
+        return Session.default.upload(data,
233
+                                      to: convertible,
234
+                                      method: method,
235
+                                      headers: headers,
236
+                                      interceptor: interceptor,
237
+                                      fileManager: fileManager)
238
+    }
239
+
240
+    /// Creates an `UploadRequest` for the given `Data` using the `URLRequestConvertible` value and `RequestInterceptor`.
241
+    ///
242
+    /// - Parameters:
243
+    ///   - data:        The `Data` to upload.
244
+    ///   - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
245
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
246
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
247
+    ///                  default.
248
+    ///
249
+    /// - Returns:       The created `UploadRequest`.
250
+    public static func upload(_ data: Data,
251
+                              with convertible: URLRequestConvertible,
252
+                              interceptor: RequestInterceptor? = nil,
253
+                              fileManager: FileManager = .default) -> UploadRequest {
254
+        return Session.default.upload(data, with: convertible, interceptor: interceptor, fileManager: fileManager)
255
+    }
256
+
257
+    // MARK: File
258
+
259
+    /// Creates an `UploadRequest` for the file at the given file `URL`, using a `URLRequest` from the provided
260
+    /// components and `RequestInterceptor`.
261
+    ///
262
+    /// - Parameters:
263
+    ///   - fileURL:     The `URL` of the file to upload.
264
+    ///   - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
265
+    ///   - method:      `HTTPMethod` for the `URLRequest`. `.post` by default.
266
+    ///   - headers:     `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
267
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `UploadRequest`. `nil` by default.
268
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
269
+    ///                  default.
270
+    ///
271
+    /// - Returns:       The created `UploadRequest`.
272
+    public static func upload(_ fileURL: URL,
273
+                              to convertible: URLConvertible,
274
+                              method: HTTPMethod = .post,
275
+                              headers: HTTPHeaders? = nil,
276
+                              interceptor: RequestInterceptor? = nil,
277
+                              fileManager: FileManager = .default) -> UploadRequest {
278
+        return Session.default.upload(fileURL,
279
+                                      to: convertible,
280
+                                      method: method,
281
+                                      headers: headers,
282
+                                      interceptor: interceptor,
283
+                                      fileManager: fileManager)
284
+    }
285
+
286
+    /// Creates an `UploadRequest` for the file at the given file `URL` using the `URLRequestConvertible` value and
287
+    /// `RequestInterceptor`.
288
+    ///
289
+    /// - Parameters:
290
+    ///   - fileURL:     The `URL` of the file to upload.
291
+    ///   - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
292
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
293
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
294
+    ///                  default.
295
+    ///
296
+    /// - Returns:       The created `UploadRequest`.
297
+    public static func upload(_ fileURL: URL,
298
+                              with convertible: URLRequestConvertible,
299
+                              interceptor: RequestInterceptor? = nil,
300
+                              fileManager: FileManager = .default) -> UploadRequest {
301
+        return Session.default.upload(fileURL, with: convertible, interceptor: interceptor, fileManager: fileManager)
302
+    }
303
+
304
+    // MARK: InputStream
305
+
306
+    /// Creates an `UploadRequest` from the `InputStream` provided using a `URLRequest` from the provided components and
307
+    /// `RequestInterceptor`.
308
+    ///
309
+    /// - Parameters:
310
+    ///   - stream:      The `InputStream` that provides the data to upload.
311
+    ///   - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
312
+    ///   - method:      `HTTPMethod` for the `URLRequest`. `.post` by default.
313
+    ///   - headers:     `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
314
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
315
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
316
+    ///                  default.
317
+    ///
318
+    /// - Returns:       The created `UploadRequest`.
319
+    public static func upload(_ stream: InputStream,
320
+                              to convertible: URLConvertible,
321
+                              method: HTTPMethod = .post,
322
+                              headers: HTTPHeaders? = nil,
323
+                              interceptor: RequestInterceptor? = nil,
324
+                              fileManager: FileManager = .default) -> UploadRequest {
325
+        return Session.default.upload(stream,
326
+                                      to: convertible,
327
+                                      method: method,
328
+                                      headers: headers,
329
+                                      interceptor: interceptor,
330
+                                      fileManager: fileManager)
331
+    }
332
+
333
+    /// Creates an `UploadRequest` from the provided `InputStream` using the `URLRequestConvertible` value and
334
+    /// `RequestInterceptor`.
335
+    ///
336
+    /// - Parameters:
337
+    ///   - stream:      The `InputStream` that provides the data to upload.
338
+    ///   - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
339
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
340
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
341
+    ///                  default.
342
+    ///
343
+    /// - Returns:       The created `UploadRequest`.
344
+    public static func upload(_ stream: InputStream,
345
+                              with convertible: URLRequestConvertible,
346
+                              interceptor: RequestInterceptor? = nil,
347
+                              fileManager: FileManager = .default) -> UploadRequest {
348
+        return Session.default.upload(stream, with: convertible, interceptor: interceptor, fileManager: fileManager)
349
+    }
350
+
351
+    // MARK: MultipartFormData
352
+
353
+    /// Creates an `UploadRequest` for the multipart form data built using a closure and sent using the provided
354
+    /// `URLRequest` components and `RequestInterceptor`.
355
+    ///
356
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
357
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
358
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
359
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
360
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
361
+    /// used for larger payloads such as video content.
362
+    ///
363
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
364
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
365
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
366
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
367
+    /// technique was used.
368
+    ///
369
+    /// - Parameters:
370
+    ///   - multipartFormData:       `MultipartFormData` building closure.
371
+    ///   - convertible:             `URLConvertible` value to be used as the `URLRequest`'s `URL`.
372
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
373
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
374
+    ///                              default.
375
+    ///   - method:                  `HTTPMethod` for the `URLRequest`. `.post` by default.
376
+    ///   - headers:                 `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
377
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
378
+    ///   - fileManager:             `FileManager` to be used if the form data exceeds the memory threshold and is
379
+    ///                              written to disk before being uploaded. `.default` instance by default.
380
+    ///
381
+    /// - Returns:                   The created `UploadRequest`.
382
+    public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
383
+                              to url: URLConvertible,
384
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
385
+                              method: HTTPMethod = .post,
386
+                              headers: HTTPHeaders? = nil,
387
+                              interceptor: RequestInterceptor? = nil,
388
+                              fileManager: FileManager = .default) -> UploadRequest {
389
+        return Session.default.upload(multipartFormData: multipartFormData,
390
+                                      to: url,
391
+                                      usingThreshold: encodingMemoryThreshold,
392
+                                      method: method,
393
+                                      headers: headers,
394
+                                      interceptor: interceptor,
395
+                                      fileManager: fileManager)
396
+    }
397
+
398
+    /// Creates an `UploadRequest` using a `MultipartFormData` building closure, the provided `URLRequestConvertible`
399
+    /// value, and a `RequestInterceptor`.
400
+    ///
401
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
402
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
403
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
404
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
405
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
406
+    /// used for larger payloads such as video content.
407
+    ///
408
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
409
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
410
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
411
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
412
+    /// technique was used.
413
+    ///
414
+    /// - Parameters:
415
+    ///   - multipartFormData:       `MultipartFormData` building closure.
416
+    ///   - request:                 `URLRequestConvertible` value to be used to create the `URLRequest`.
417
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
418
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
419
+    ///                              default.
420
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
421
+    ///   - fileManager:             `FileManager` to be used if the form data exceeds the memory threshold and is
422
+    ///                              written to disk before being uploaded. `.default` instance by default.
423
+    ///
424
+    /// - Returns:                   The created `UploadRequest`.
425
+    public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
426
+                              with request: URLRequestConvertible,
427
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
428
+                              interceptor: RequestInterceptor? = nil,
429
+                              fileManager: FileManager = .default) -> UploadRequest {
430
+        return Session.default.upload(multipartFormData: multipartFormData,
431
+                                      with: request,
432
+                                      usingThreshold: encodingMemoryThreshold,
433
+                                      interceptor: interceptor,
434
+                                      fileManager: fileManager)
435
+    }
436
+
437
+    /// Creates an `UploadRequest` for the prebuilt `MultipartFormData` value using the provided `URLRequest` components
438
+    /// and `RequestInterceptor`.
439
+    ///
440
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
441
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
442
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
443
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
444
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
445
+    /// used for larger payloads such as video content.
446
+    ///
447
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
448
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
449
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
450
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
451
+    /// technique was used.
452
+    ///
453
+    /// - Parameters:
454
+    ///   - multipartFormData:       `MultipartFormData` instance to upload.
455
+    ///   - url:                     `URLConvertible` value to be used as the `URLRequest`'s `URL`.
456
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
457
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
458
+    ///                              default.
459
+    ///   - method:                  `HTTPMethod` for the `URLRequest`. `.post` by default.
460
+    ///   - headers:                 `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
461
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
462
+    ///   - fileManager:             `FileManager` to be used if the form data exceeds the memory threshold and is
463
+    ///                              written to disk before being uploaded. `.default` instance by default.
464
+    ///
465
+    /// - Returns:                   The created `UploadRequest`.
466
+    public static func upload(multipartFormData: MultipartFormData,
467
+                              to url: URLConvertible,
468
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
469
+                              method: HTTPMethod = .post,
470
+                              headers: HTTPHeaders? = nil,
471
+                              interceptor: RequestInterceptor? = nil,
472
+                              fileManager: FileManager = .default) -> UploadRequest {
473
+        return Session.default.upload(multipartFormData: multipartFormData,
474
+                                      to: url,
475
+                                      usingThreshold: encodingMemoryThreshold,
476
+                                      method: method,
477
+                                      headers: headers,
478
+                                      interceptor: interceptor,
479
+                                      fileManager: fileManager)
480
+    }
481
+
482
+    /// Creates an `UploadRequest` for the prebuilt `MultipartFormData` value using the providing `URLRequestConvertible`
483
+    /// value and `RequestInterceptor`.
484
+    ///
485
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
486
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
487
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
488
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
489
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
490
+    /// used for larger payloads such as video content.
491
+    ///
492
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
493
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
494
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
495
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
496
+    /// technique was used.
497
+    ///
498
+    /// - Parameters:
499
+    ///   - multipartFormData:       `MultipartFormData` instance to upload.
500
+    ///   - request:                 `URLRequestConvertible` value to be used to create the `URLRequest`.
501
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
502
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
503
+    ///                              default.
504
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
505
+    ///   - fileManager:             `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
506
+    ///                              default.
507
+    ///
508
+    /// - Returns:                   The created `UploadRequest`.
509
+    public static func upload(multipartFormData: MultipartFormData,
510
+                              with request: URLRequestConvertible,
511
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
512
+                              interceptor: RequestInterceptor? = nil,
513
+                              fileManager: FileManager = .default) -> UploadRequest {
514
+        return Session.default.upload(multipartFormData: multipartFormData,
515
+                                      with: request,
516
+                                      usingThreshold: encodingMemoryThreshold,
517
+                                      interceptor: interceptor,
518
+                                      fileManager: fileManager)
519
+    }
520
+}

+ 58
- 0
Pods/Alamofire/Source/AlamofireExtended.swift View File

@@ -0,0 +1,58 @@
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 metatype of any extended type.
28
+    let type: ExtendedType
29
+
30
+    init(_ type: ExtendedType) {
31
+        self.type = type
32
+    }
33
+}
34
+
35
+/// Protocol describing the `af` extension points for Alamofire extended types.
36
+public protocol AlamofireExtended {
37
+    /// Type being extended.
38
+    associatedtype ExtendedType
39
+
40
+    /// Static Alamofire extension point.
41
+    static var af: AlamofireExtension<ExtendedType>.Type { get set }
42
+    /// Instance Alamofire extension point.
43
+    var af: AlamofireExtension<ExtendedType> { get set }
44
+}
45
+
46
+public extension AlamofireExtended {
47
+    /// Static Alamofire extension point.
48
+    static var af: AlamofireExtension<Self>.Type {
49
+        get { return AlamofireExtension<Self>.self }
50
+        set {}
51
+    }
52
+
53
+    /// Instance Alamofire extension point.
54
+    var af: AlamofireExtension<Self> {
55
+        get { return AlamofireExtension(self) }
56
+        set {}
57
+    }
58
+}

+ 91
- 0
Pods/Alamofire/Source/CachedResponseHandler.swift View File

@@ -0,0 +1,91 @@
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 follow `Behavior`.
62
+    public static let cache = ResponseCacher(behavior: .cache)
63
+    /// Returns a `ResponseCacher` with a do not follow `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
+}

+ 37
- 0
Pods/Alamofire/Source/DispatchQueue+Alamofire.swift View File

@@ -0,0 +1,37 @@
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
+}

+ 844
- 0
Pods/Alamofire/Source/EventMonitor.swift View File

@@ -0,0 +1,844 @@
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
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
69
+    func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask)
70
+
71
+    // MARK: URLSessionDataDelegate Events
72
+
73
+    /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:didReceive:)` method.
74
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
75
+
76
+    /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:willCacheResponse:completionHandler:)` method.
77
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse)
78
+
79
+    // MARK: URLSessionDownloadDelegate Events
80
+
81
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` method.
82
+    func urlSession(_ session: URLSession,
83
+                    downloadTask: URLSessionDownloadTask,
84
+                    didResumeAtOffset fileOffset: Int64,
85
+                    expectedTotalBytes: Int64)
86
+
87
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)` method.
88
+    func urlSession(_ session: URLSession,
89
+                    downloadTask: URLSessionDownloadTask,
90
+                    didWriteData bytesWritten: Int64,
91
+                    totalBytesWritten: Int64,
92
+                    totalBytesExpectedToWrite: Int64)
93
+
94
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didFinishDownloadingTo:)` method.
95
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
96
+
97
+    // MARK: - Request Events
98
+
99
+    /// Event called when a `URLRequest` is first created for a `Request`. If a `RequestAdapter` is active, the
100
+    /// `URLRequest` will be adapted before being issued.
101
+    func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest)
102
+
103
+    /// Event called when the attempt to create a `URLRequest` from a `Request`'s original `URLRequestConvertible` value fails.
104
+    func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError)
105
+
106
+    /// Event called when a `RequestAdapter` adapts the `Request`'s initial `URLRequest`.
107
+    func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest)
108
+
109
+    /// Event called when a `RequestAdapter` fails to adapt the `Request`'s initial `URLRequest`.
110
+    func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError)
111
+
112
+    /// Event called when a final `URLRequest` is created for a `Request`.
113
+    func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest)
114
+
115
+    /// Event called when a `URLSessionTask` subclass instance is created for a `Request`.
116
+    func request(_ request: Request, didCreateTask task: URLSessionTask)
117
+
118
+    /// Event called when a `Request` receives a `URLSessionTaskMetrics` value.
119
+    func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics)
120
+
121
+    /// Event called when a `Request` fails due to an error created by Alamofire. e.g. When certificate pinning fails.
122
+    func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError)
123
+
124
+    /// Event called when a `Request`'s task completes, possibly with an error. A `Request` may receive this event
125
+    /// multiple times if it is retried.
126
+    func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?)
127
+
128
+    /// Event called when a `Request` is about to be retried.
129
+    func requestIsRetrying(_ request: Request)
130
+
131
+    /// Event called when a `Request` finishes and response serializers are being called.
132
+    func requestDidFinish(_ request: Request)
133
+
134
+    /// Event called when a `Request` receives a `resume` call.
135
+    func requestDidResume(_ request: Request)
136
+
137
+    /// Event called when a `Request`'s associated `URLSessionTask` is resumed.
138
+    func request(_ request: Request, didResumeTask task: URLSessionTask)
139
+
140
+    /// Event called when a `Request` receives a `suspend` call.
141
+    func requestDidSuspend(_ request: Request)
142
+
143
+    /// Event called when a `Request`'s associated `URLSessionTask` is suspended.
144
+    func request(_ request: Request, didSuspendTask task: URLSessionTask)
145
+
146
+    /// Event called when a `Request` receives a `cancel` call.
147
+    func requestDidCancel(_ request: Request)
148
+
149
+    /// Event called when a `Request`'s associated `URLSessionTask` is cancelled.
150
+    func request(_ request: Request, didCancelTask task: URLSessionTask)
151
+
152
+    // MARK: DataRequest Events
153
+
154
+    /// Event called when a `DataRequest` calls a `Validation`.
155
+    func request(_ request: DataRequest,
156
+                 didValidateRequest urlRequest: URLRequest?,
157
+                 response: HTTPURLResponse,
158
+                 data: Data?,
159
+                 withResult result: Request.ValidationResult)
160
+
161
+    /// Event called when a `DataRequest` creates a `DataResponse<Data?>` value without calling a `ResponseSerializer`.
162
+    func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>)
163
+
164
+    /// Event called when a `DataRequest` calls a `ResponseSerializer` and creates a generic `DataResponse<Value, AFError>`.
165
+    func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>)
166
+
167
+    // MARK: UploadRequest Events
168
+
169
+    /// Event called when an `UploadRequest` creates its `Uploadable` value, indicating the type of upload it represents.
170
+    func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable)
171
+
172
+    /// Event called when an `UploadRequest` failed to create its `Uploadable` value due to an error.
173
+    func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError)
174
+
175
+    /// Event called when an `UploadRequest` provides the `InputStream` from its `Uploadable` value. This only occurs if
176
+    /// the `InputStream` does not wrap a `Data` value or file `URL`.
177
+    func request(_ request: UploadRequest, didProvideInputStream stream: InputStream)
178
+
179
+    // MARK: DownloadRequest Events
180
+
181
+    /// Event called when a `DownloadRequest`'s `URLSessionDownloadTask` finishes and the temporary file has been moved.
182
+    func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>)
183
+
184
+    /// Event called when a `DownloadRequest`'s `Destination` closure is called and creates the destination URL the
185
+    /// downloaded file will be moved to.
186
+    func request(_ request: DownloadRequest, didCreateDestinationURL url: URL)
187
+
188
+    /// Event called when a `DownloadRequest` calls a `Validation`.
189
+    func request(_ request: DownloadRequest,
190
+                 didValidateRequest urlRequest: URLRequest?,
191
+                 response: HTTPURLResponse,
192
+                 fileURL: URL?,
193
+                 withResult result: Request.ValidationResult)
194
+
195
+    /// Event called when a `DownloadRequest` creates a `DownloadResponse<URL?, AFError>` without calling a `ResponseSerializer`.
196
+    func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>)
197
+
198
+    /// Event called when a `DownloadRequest` calls a `DownloadResponseSerializer` and creates a generic `DownloadResponse<Value, AFError>`
199
+    func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>)
200
+}
201
+
202
+extension EventMonitor {
203
+    /// The default queue on which `CompositeEventMonitor`s will call the `EventMonitor` methods. `.main` by default.
204
+    public var queue: DispatchQueue { return .main }
205
+
206
+    // MARK: Default Implementations
207
+
208
+    public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {}
209
+    public func urlSession(_ session: URLSession,
210
+                           task: URLSessionTask,
211
+                           didReceive challenge: URLAuthenticationChallenge) {}
212
+    public func urlSession(_ session: URLSession,
213
+                           task: URLSessionTask,
214
+                           didSendBodyData bytesSent: Int64,
215
+                           totalBytesSent: Int64,
216
+                           totalBytesExpectedToSend: Int64) {}
217
+    public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {}
218
+    public func urlSession(_ session: URLSession,
219
+                           task: URLSessionTask,
220
+                           willPerformHTTPRedirection response: HTTPURLResponse,
221
+                           newRequest request: URLRequest) {}
222
+    public func urlSession(_ session: URLSession,
223
+                           task: URLSessionTask,
224
+                           didFinishCollecting metrics: URLSessionTaskMetrics) {}
225
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {}
226
+    public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {}
227
+    public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
228
+    public func urlSession(_ session: URLSession,
229
+                           dataTask: URLSessionDataTask,
230
+                           willCacheResponse proposedResponse: CachedURLResponse) {}
231
+    public func urlSession(_ session: URLSession,
232
+                           downloadTask: URLSessionDownloadTask,
233
+                           didResumeAtOffset fileOffset: Int64,
234
+                           expectedTotalBytes: Int64) {}
235
+    public func urlSession(_ session: URLSession,
236
+                           downloadTask: URLSessionDownloadTask,
237
+                           didWriteData bytesWritten: Int64,
238
+                           totalBytesWritten: Int64,
239
+                           totalBytesExpectedToWrite: Int64) {}
240
+    public func urlSession(_ session: URLSession,
241
+                           downloadTask: URLSessionDownloadTask,
242
+                           didFinishDownloadingTo location: URL) {}
243
+    public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {}
244
+    public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {}
245
+    public func request(_ request: Request,
246
+                        didAdaptInitialRequest initialRequest: URLRequest,
247
+                        to adaptedRequest: URLRequest) {}
248
+    public func request(_ request: Request,
249
+                        didFailToAdaptURLRequest initialRequest: URLRequest,
250
+                        withError error: AFError) {}
251
+    public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {}
252
+    public func request(_ request: Request, didCreateTask task: URLSessionTask) {}
253
+    public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {}
254
+    public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {}
255
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {}
256
+    public func requestIsRetrying(_ request: Request) {}
257
+    public func requestDidFinish(_ request: Request) {}
258
+    public func requestDidResume(_ request: Request) {}
259
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {}
260
+    public func requestDidSuspend(_ request: Request) {}
261
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {}
262
+    public func requestDidCancel(_ request: Request) {}
263
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {}
264
+    public func request(_ request: DataRequest,
265
+                        didValidateRequest urlRequest: URLRequest?,
266
+                        response: HTTPURLResponse,
267
+                        data: Data?,
268
+                        withResult result: Request.ValidationResult) {}
269
+    public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {}
270
+    public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {}
271
+    public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {}
272
+    public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {}
273
+    public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {}
274
+    public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {}
275
+    public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {}
276
+    public func request(_ request: DownloadRequest,
277
+                        didValidateRequest urlRequest: URLRequest?,
278
+                        response: HTTPURLResponse,
279
+                        fileURL: URL?,
280
+                        withResult result: Request.ValidationResult) {}
281
+    public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {}
282
+    public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {}
283
+}
284
+
285
+/// An `EventMonitor` which can contain multiple `EventMonitor`s and calls their methods on their queues.
286
+public final class CompositeEventMonitor: EventMonitor {
287
+    public let queue = DispatchQueue(label: "org.alamofire.compositeEventMonitor", qos: .background)
288
+
289
+    let monitors: [EventMonitor]
290
+
291
+    init(monitors: [EventMonitor]) {
292
+        self.monitors = monitors
293
+    }
294
+
295
+    func performEvent(_ event: @escaping (EventMonitor) -> Void) {
296
+        queue.async {
297
+            for monitor in self.monitors {
298
+                monitor.queue.async { event(monitor) }
299
+            }
300
+        }
301
+    }
302
+
303
+    public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
304
+        performEvent { $0.urlSession(session, didBecomeInvalidWithError: error) }
305
+    }
306
+
307
+    public func urlSession(_ session: URLSession,
308
+                           task: URLSessionTask,
309
+                           didReceive challenge: URLAuthenticationChallenge) {
310
+        performEvent { $0.urlSession(session, task: task, didReceive: challenge) }
311
+    }
312
+
313
+    public func urlSession(_ session: URLSession,
314
+                           task: URLSessionTask,
315
+                           didSendBodyData bytesSent: Int64,
316
+                           totalBytesSent: Int64,
317
+                           totalBytesExpectedToSend: Int64) {
318
+        performEvent {
319
+            $0.urlSession(session,
320
+                          task: task,
321
+                          didSendBodyData: bytesSent,
322
+                          totalBytesSent: totalBytesSent,
323
+                          totalBytesExpectedToSend: totalBytesExpectedToSend)
324
+        }
325
+    }
326
+
327
+    public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
328
+        performEvent {
329
+            $0.urlSession(session, taskNeedsNewBodyStream: task)
330
+        }
331
+    }
332
+
333
+    public func urlSession(_ session: URLSession,
334
+                           task: URLSessionTask,
335
+                           willPerformHTTPRedirection response: HTTPURLResponse,
336
+                           newRequest request: URLRequest) {
337
+        performEvent {
338
+            $0.urlSession(session,
339
+                          task: task,
340
+                          willPerformHTTPRedirection: response,
341
+                          newRequest: request)
342
+        }
343
+    }
344
+
345
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
346
+        performEvent { $0.urlSession(session, task: task, didFinishCollecting: metrics) }
347
+    }
348
+
349
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
350
+        performEvent { $0.urlSession(session, task: task, didCompleteWithError: error) }
351
+    }
352
+
353
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
354
+    public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
355
+        performEvent { $0.urlSession(session, taskIsWaitingForConnectivity: task) }
356
+    }
357
+
358
+    public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
359
+        performEvent { $0.urlSession(session, dataTask: dataTask, didReceive: data) }
360
+    }
361
+
362
+    public func urlSession(_ session: URLSession,
363
+                           dataTask: URLSessionDataTask,
364
+                           willCacheResponse proposedResponse: CachedURLResponse) {
365
+        performEvent { $0.urlSession(session, dataTask: dataTask, willCacheResponse: proposedResponse) }
366
+    }
367
+
368
+    public func urlSession(_ session: URLSession,
369
+                           downloadTask: URLSessionDownloadTask,
370
+                           didResumeAtOffset fileOffset: Int64,
371
+                           expectedTotalBytes: Int64) {
372
+        performEvent {
373
+            $0.urlSession(session,
374
+                          downloadTask: downloadTask,
375
+                          didResumeAtOffset: fileOffset,
376
+                          expectedTotalBytes: expectedTotalBytes)
377
+        }
378
+    }
379
+
380
+    public func urlSession(_ session: URLSession,
381
+                           downloadTask: URLSessionDownloadTask,
382
+                           didWriteData bytesWritten: Int64,
383
+                           totalBytesWritten: Int64,
384
+                           totalBytesExpectedToWrite: Int64) {
385
+        performEvent {
386
+            $0.urlSession(session,
387
+                          downloadTask: downloadTask,
388
+                          didWriteData: bytesWritten,
389
+                          totalBytesWritten: totalBytesWritten,
390
+                          totalBytesExpectedToWrite: totalBytesExpectedToWrite)
391
+        }
392
+    }
393
+
394
+    public func urlSession(_ session: URLSession,
395
+                           downloadTask: URLSessionDownloadTask,
396
+                           didFinishDownloadingTo location: URL) {
397
+        performEvent { $0.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location) }
398
+    }
399
+
400
+    public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
401
+        performEvent { $0.request(request, didCreateInitialURLRequest: urlRequest) }
402
+    }
403
+
404
+    public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
405
+        performEvent { $0.request(request, didFailToCreateURLRequestWithError: error) }
406
+    }
407
+
408
+    public func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
409
+        performEvent { $0.request(request, didAdaptInitialRequest: initialRequest, to: adaptedRequest) }
410
+    }
411
+
412
+    public func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
413
+        performEvent { $0.request(request, didFailToAdaptURLRequest: initialRequest, withError: error) }
414
+    }
415
+
416
+    public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
417
+        performEvent { $0.request(request, didCreateURLRequest: urlRequest) }
418
+    }
419
+
420
+    public func request(_ request: Request, didCreateTask task: URLSessionTask) {
421
+        performEvent { $0.request(request, didCreateTask: task) }
422
+    }
423
+
424
+    public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
425
+        performEvent { $0.request(request, didGatherMetrics: metrics) }
426
+    }
427
+
428
+    public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
429
+        performEvent { $0.request(request, didFailTask: task, earlyWithError: error) }
430
+    }
431
+
432
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
433
+        performEvent { $0.request(request, didCompleteTask: task, with: error) }
434
+    }
435
+
436
+    public func requestIsRetrying(_ request: Request) {
437
+        performEvent { $0.requestIsRetrying(request) }
438
+    }
439
+
440
+    public func requestDidFinish(_ request: Request) {
441
+        performEvent { $0.requestDidFinish(request) }
442
+    }
443
+
444
+    public func requestDidResume(_ request: Request) {
445
+        performEvent { $0.requestDidResume(request) }
446
+    }
447
+
448
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
449
+        performEvent { $0.request(request, didResumeTask: task) }
450
+    }
451
+
452
+    public func requestDidSuspend(_ request: Request) {
453
+        performEvent { $0.requestDidSuspend(request) }
454
+    }
455
+
456
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
457
+        performEvent { $0.request(request, didSuspendTask: task) }
458
+    }
459
+
460
+    public func requestDidCancel(_ request: Request) {
461
+        performEvent { $0.requestDidCancel(request) }
462
+    }
463
+
464
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
465
+        performEvent { $0.request(request, didCancelTask: task) }
466
+    }
467
+
468
+    public func request(_ request: DataRequest,
469
+                        didValidateRequest urlRequest: URLRequest?,
470
+                        response: HTTPURLResponse,
471
+                        data: Data?,
472
+                        withResult result: Request.ValidationResult) {
473
+        performEvent { $0.request(request,
474
+                                  didValidateRequest: urlRequest,
475
+                                  response: response,
476
+                                  data: data,
477
+                                  withResult: result)
478
+        }
479
+    }
480
+
481
+    public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
482
+        performEvent { $0.request(request, didParseResponse: response) }
483
+    }
484
+
485
+    public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {
486
+        performEvent { $0.request(request, didParseResponse: response) }
487
+    }
488
+
489
+    public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
490
+        performEvent { $0.request(request, didCreateUploadable: uploadable) }
491
+    }
492
+
493
+    public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
494
+        performEvent { $0.request(request, didFailToCreateUploadableWithError: error) }
495
+    }
496
+
497
+    public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
498
+        performEvent { $0.request(request, didProvideInputStream: stream) }
499
+    }
500
+
501
+    public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
502
+        performEvent { $0.request(request, didFinishDownloadingUsing: task, with: result) }
503
+    }
504
+
505
+    public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
506
+        performEvent { $0.request(request, didCreateDestinationURL: url) }
507
+    }
508
+
509
+    public func request(_ request: DownloadRequest,
510
+                        didValidateRequest urlRequest: URLRequest?,
511
+                        response: HTTPURLResponse,
512
+                        fileURL: URL?,
513
+                        withResult result: Request.ValidationResult) {
514
+        performEvent { $0.request(request,
515
+                                  didValidateRequest: urlRequest,
516
+                                  response: response,
517
+                                  fileURL: fileURL,
518
+                                  withResult: result) }
519
+    }
520
+
521
+    public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
522
+        performEvent { $0.request(request, didParseResponse: response) }
523
+    }
524
+
525
+    public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {
526
+        performEvent { $0.request(request, didParseResponse: response) }
527
+    }
528
+}
529
+
530
+/// `EventMonitor` that allows optional closures to be set to receive events.
531
+open class ClosureEventMonitor: EventMonitor {
532
+    /// Closure called on the `urlSession(_:didBecomeInvalidWithError:)` event.
533
+    open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
534
+
535
+    /// Closure called on the `urlSession(_:task:didReceive:completionHandler:)`.
536
+    open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> Void)?
537
+
538
+    /// Closure that receives `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)` event.
539
+    open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
540
+
541
+    /// Closure called on the `urlSession(_:task:needNewBodyStream:)` event.
542
+    open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> Void)?
543
+
544
+    /// Closure called on the `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` event.
545
+    open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> Void)?
546
+
547
+    /// Closure called on the `urlSession(_:task:didFinishCollecting:)` event.
548
+    open var taskDidFinishCollectingMetrics: ((URLSession, URLSessionTask, URLSessionTaskMetrics) -> Void)?
549
+
550
+    /// Closure called on the `urlSession(_:task:didCompleteWithError:)` event.
551
+    open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)?
552
+
553
+    /// Closure called on the `urlSession(_:taskIsWaitingForConnectivity:)` event.
554
+    open var taskIsWaitingForConnectivity: ((URLSession, URLSessionTask) -> Void)?
555
+
556
+    /// Closure that receives the `urlSession(_:dataTask:didReceive:)` event.
557
+    open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
558
+
559
+    /// Closure called on the `urlSession(_:dataTask:willCacheResponse:completionHandler:)` event.
560
+    open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> Void)?
561
+
562
+    /// Closure called on the `urlSession(_:downloadTask:didFinishDownloadingTo:)` event.
563
+    open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)?
564
+
565
+    /// Closure called on the `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`
566
+    /// event.
567
+    open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
568
+
569
+    /// Closure called on the `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` event.
570
+    open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
571
+
572
+    // MARK: - Request Events
573
+
574
+    /// Closure called on the `request(_:didCreateInitialURLRequest:)` event.
575
+    open var requestDidCreateInitialURLRequest: ((Request, URLRequest) -> Void)?
576
+
577
+    /// Closure called on the `request(_:didFailToCreateURLRequestWithError:)` event.
578
+    open var requestDidFailToCreateURLRequestWithError: ((Request, AFError) -> Void)?
579
+
580
+    /// Closure called on the `request(_:didAdaptInitialRequest:to:)` event.
581
+    open var requestDidAdaptInitialRequestToAdaptedRequest: ((Request, URLRequest, URLRequest) -> Void)?
582
+
583
+    /// Closure called on the `request(_:didFailToAdaptURLRequest:withError:)` event.
584
+    open var requestDidFailToAdaptURLRequestWithError: ((Request, URLRequest, AFError) -> Void)?
585
+
586
+    /// Closure called on the `request(_:didCreateURLRequest:)` event.
587
+    open var requestDidCreateURLRequest: ((Request, URLRequest) -> Void)?
588
+
589
+    /// Closure called on the `request(_:didCreateTask:)` event.
590
+    open var requestDidCreateTask: ((Request, URLSessionTask) -> Void)?
591
+
592
+    /// Closure called on the `request(_:didGatherMetrics:)` event.
593
+    open var requestDidGatherMetrics: ((Request, URLSessionTaskMetrics) -> Void)?
594
+
595
+    /// Closure called on the `request(_:didFailTask:earlyWithError:)` event.
596
+    open var requestDidFailTaskEarlyWithError: ((Request, URLSessionTask, AFError) -> Void)?
597
+
598
+    /// Closure called on the `request(_:didCompleteTask:with:)` event.
599
+    open var requestDidCompleteTaskWithError: ((Request, URLSessionTask, AFError?) -> Void)?
600
+
601
+    /// Closure called on the `requestIsRetrying(_:)` event.
602
+    open var requestIsRetrying: ((Request) -> Void)?
603
+
604
+    /// Closure called on the `requestDidFinish(_:)` event.
605
+    open var requestDidFinish: ((Request) -> Void)?
606
+
607
+    /// Closure called on the `requestDidResume(_:)` event.
608
+    open var requestDidResume: ((Request) -> Void)?
609
+
610
+    /// Closure called on the `request(_:didResumeTask:)` event.
611
+    open var requestDidResumeTask: ((Request, URLSessionTask) -> Void)?
612
+
613
+    /// Closure called on the `requestDidSuspend(_:)` event.
614
+    open var requestDidSuspend: ((Request) -> Void)?
615
+
616
+    /// Closure called on the `request(_:didSuspendTask:)` event.
617
+    open var requestDidSuspendTask: ((Request, URLSessionTask) -> Void)?
618
+
619
+    /// Closure called on the `requestDidCancel(_:)` event.
620
+    open var requestDidCancel: ((Request) -> Void)?
621
+
622
+    /// Closure called on the `request(_:didCancelTask:)` event.
623
+    open var requestDidCancelTask: ((Request, URLSessionTask) -> Void)?
624
+
625
+    /// Closure called on the `request(_:didValidateRequest:response:data:withResult:)` event.
626
+    open var requestDidValidateRequestResponseDataWithResult: ((DataRequest, URLRequest?, HTTPURLResponse, Data?, Request.ValidationResult) -> Void)?
627
+
628
+    /// Closure called on the `request(_:didParseResponse:)` event.
629
+    open var requestDidParseResponse: ((DataRequest, DataResponse<Data?, AFError>) -> Void)?
630
+
631
+    /// Closure called on the `request(_:didCreateUploadable:)` event.
632
+    open var requestDidCreateUploadable: ((UploadRequest, UploadRequest.Uploadable) -> Void)?
633
+
634
+    /// Closure called on the `request(_:didFailToCreateUploadableWithError:)` event.
635
+    open var requestDidFailToCreateUploadableWithError: ((UploadRequest, AFError) -> Void)?
636
+
637
+    /// Closure called on the `request(_:didProvideInputStream:)` event.
638
+    open var requestDidProvideInputStream: ((UploadRequest, InputStream) -> Void)?
639
+
640
+    /// Closure called on the `request(_:didFinishDownloadingUsing:with:)` event.
641
+    open var requestDidFinishDownloadingUsingTaskWithResult: ((DownloadRequest, URLSessionTask, Result<URL, AFError>) -> Void)?
642
+
643
+    /// Closure called on the `request(_:didCreateDestinationURL:)` event.
644
+    open var requestDidCreateDestinationURL: ((DownloadRequest, URL) -> Void)?
645
+
646
+    /// Closure called on the `request(_:didValidateRequest:response:temporaryURL:destinationURL:withResult:)` event.
647
+    open var requestDidValidateRequestResponseFileURLWithResult: ((DownloadRequest, URLRequest?, HTTPURLResponse, URL?, Request.ValidationResult) -> Void)?
648
+
649
+    /// Closure called on the `request(_:didParseResponse:)` event.
650
+    open var requestDidParseDownloadResponse: ((DownloadRequest, DownloadResponse<URL?, AFError>) -> Void)?
651
+
652
+    public let queue: DispatchQueue
653
+
654
+    /// Creates an instance using the provided queue.
655
+    ///
656
+    /// - Parameter queue: `DispatchQueue` on which events will fired. `.main` by default.
657
+    public init(queue: DispatchQueue = .main) {
658
+        self.queue = queue
659
+    }
660
+
661
+    open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
662
+        sessionDidBecomeInvalidWithError?(session, error)
663
+    }
664
+
665
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge) {
666
+        taskDidReceiveChallenge?(session, task, challenge)
667
+    }
668
+
669
+    open func urlSession(_ session: URLSession,
670
+                         task: URLSessionTask,
671
+                         didSendBodyData bytesSent: Int64,
672
+                         totalBytesSent: Int64,
673
+                         totalBytesExpectedToSend: Int64) {
674
+        taskDidSendBodyData?(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
675
+    }
676
+
677
+    open func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
678
+        taskNeedNewBodyStream?(session, task)
679
+    }
680
+
681
+    open func urlSession(_ session: URLSession,
682
+                         task: URLSessionTask,
683
+                         willPerformHTTPRedirection response: HTTPURLResponse,
684
+                         newRequest request: URLRequest) {
685
+        taskWillPerformHTTPRedirection?(session, task, response, request)
686
+    }
687
+
688
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
689
+        taskDidFinishCollectingMetrics?(session, task, metrics)
690
+    }
691
+
692
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
693
+        taskDidComplete?(session, task, error)
694
+    }
695
+
696
+    open func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
697
+        taskIsWaitingForConnectivity?(session, task)
698
+    }
699
+
700
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
701
+        dataTaskDidReceiveData?(session, dataTask, data)
702
+    }
703
+
704
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse) {
705
+        dataTaskWillCacheResponse?(session, dataTask, proposedResponse)
706
+    }
707
+
708
+    open func urlSession(_ session: URLSession,
709
+                         downloadTask: URLSessionDownloadTask,
710
+                         didResumeAtOffset fileOffset: Int64,
711
+                         expectedTotalBytes: Int64) {
712
+        downloadTaskDidResumeAtOffset?(session, downloadTask, fileOffset, expectedTotalBytes)
713
+    }
714
+
715
+    open func urlSession(_ session: URLSession,
716
+                         downloadTask: URLSessionDownloadTask,
717
+                         didWriteData bytesWritten: Int64,
718
+                         totalBytesWritten: Int64,
719
+                         totalBytesExpectedToWrite: Int64) {
720
+        downloadTaskDidWriteData?(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
721
+    }
722
+
723
+    open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
724
+        downloadTaskDidFinishDownloadingToURL?(session, downloadTask, location)
725
+    }
726
+
727
+    // MARK: Request Events
728
+
729
+    open func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
730
+        requestDidCreateInitialURLRequest?(request, urlRequest)
731
+    }
732
+
733
+    open func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
734
+        requestDidFailToCreateURLRequestWithError?(request, error)
735
+    }
736
+
737
+    open func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
738
+        requestDidAdaptInitialRequestToAdaptedRequest?(request, initialRequest, adaptedRequest)
739
+    }
740
+
741
+    open func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
742
+        requestDidFailToAdaptURLRequestWithError?(request, initialRequest, error)
743
+    }
744
+
745
+    open func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
746
+        requestDidCreateURLRequest?(request, urlRequest)
747
+    }
748
+
749
+    open func request(_ request: Request, didCreateTask task: URLSessionTask) {
750
+        requestDidCreateTask?(request, task)
751
+    }
752
+
753
+    open func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
754
+        requestDidGatherMetrics?(request, metrics)
755
+    }
756
+
757
+    open func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
758
+        requestDidFailTaskEarlyWithError?(request, task, error)
759
+    }
760
+
761
+    open func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
762
+        requestDidCompleteTaskWithError?(request, task, error)
763
+    }
764
+
765
+    open func requestIsRetrying(_ request: Request) {
766
+        requestIsRetrying?(request)
767
+    }
768
+
769
+    open func requestDidFinish(_ request: Request) {
770
+        requestDidFinish?(request)
771
+    }
772
+
773
+    open func requestDidResume(_ request: Request) {
774
+        requestDidResume?(request)
775
+    }
776
+
777
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
778
+        requestDidResumeTask?(request, task)
779
+    }
780
+
781
+    open func requestDidSuspend(_ request: Request) {
782
+        requestDidSuspend?(request)
783
+    }
784
+
785
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
786
+        requestDidSuspendTask?(request, task)
787
+    }
788
+
789
+    open func requestDidCancel(_ request: Request) {
790
+        requestDidCancel?(request)
791
+    }
792
+
793
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
794
+        requestDidCancelTask?(request, task)
795
+    }
796
+
797
+    open func request(_ request: DataRequest,
798
+                      didValidateRequest urlRequest: URLRequest?,
799
+                      response: HTTPURLResponse,
800
+                      data: Data?,
801
+                      withResult result: Request.ValidationResult) {
802
+        requestDidValidateRequestResponseDataWithResult?(request, urlRequest, response, data, result)
803
+    }
804
+
805
+    open func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
806
+        requestDidParseResponse?(request, response)
807
+    }
808
+
809
+    open func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
810
+        requestDidCreateUploadable?(request, uploadable)
811
+    }
812
+
813
+    open func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
814
+        requestDidFailToCreateUploadableWithError?(request, error)
815
+    }
816
+
817
+    open func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
818
+        requestDidProvideInputStream?(request, stream)
819
+    }
820
+
821
+    open func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
822
+        requestDidFinishDownloadingUsingTaskWithResult?(request, task, result)
823
+    }
824
+
825
+    open func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
826
+        requestDidCreateDestinationURL?(request, url)
827
+    }
828
+
829
+    open func request(_ request: DownloadRequest,
830
+                      didValidateRequest urlRequest: URLRequest?,
831
+                      response: HTTPURLResponse,
832
+                      fileURL: URL?,
833
+                      withResult result: Request.ValidationResult) {
834
+        requestDidValidateRequestResponseFileURLWithResult?(request,
835
+                                                            urlRequest,
836
+                                                            response,
837
+                                                            fileURL,
838
+                                                            result)
839
+    }
840
+
841
+    open func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
842
+        requestDidParseDownloadResponse?(request, response)
843
+    }
844
+}

+ 445
- 0
Pods/Alamofire/Source/HTTPHeaders.swift View File

@@ -0,0 +1,445 @@
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.
97
+    public mutating func sort() {
98
+        headers.sort { $0.name < $1.name }
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
+        return HTTPHeaders(headers.sorted { $0.name < $1.name })
106
+    }
107
+
108
+    /// Case-insensitively find a header's value by name.
109
+    ///
110
+    /// - Parameter name: The name of the header to search for, case-insensitively.
111
+    ///
112
+    /// - Returns:        The value of header, if it exists.
113
+    public func value(for name: String) -> String? {
114
+        guard let index = headers.index(of: name) else { return nil }
115
+
116
+        return headers[index].value
117
+    }
118
+
119
+    /// Case-insensitively access the header with the given name.
120
+    ///
121
+    /// - Parameter name: The name of the header.
122
+    public subscript(_ name: String) -> String? {
123
+        get { return value(for: name) }
124
+        set {
125
+            if let value = newValue {
126
+                update(name: name, value: value)
127
+            } else {
128
+                remove(name: name)
129
+            }
130
+        }
131
+    }
132
+
133
+    /// The dictionary representation of all headers.
134
+    ///
135
+    /// This representation does not preserve the current order of the instance.
136
+    public var dictionary: [String: String] {
137
+        let namesAndValues = headers.map { ($0.name, $0.value) }
138
+
139
+        return Dictionary(namesAndValues, uniquingKeysWith: { _, last in last })
140
+    }
141
+}
142
+
143
+extension HTTPHeaders: ExpressibleByDictionaryLiteral {
144
+    public init(dictionaryLiteral elements: (String, String)...) {
145
+        self.init()
146
+
147
+        elements.forEach { update(name: $0.0, value: $0.1) }
148
+    }
149
+}
150
+
151
+extension HTTPHeaders: ExpressibleByArrayLiteral {
152
+    public init(arrayLiteral elements: HTTPHeader...) {
153
+        self.init(elements)
154
+    }
155
+}
156
+
157
+extension HTTPHeaders: Sequence {
158
+    public func makeIterator() -> IndexingIterator<[HTTPHeader]> {
159
+        return headers.makeIterator()
160
+    }
161
+}
162
+
163
+extension HTTPHeaders: Collection {
164
+    public var startIndex: Int {
165
+        return headers.startIndex
166
+    }
167
+
168
+    public var endIndex: Int {
169
+        return headers.endIndex
170
+    }
171
+
172
+    public subscript(position: Int) -> HTTPHeader {
173
+        return headers[position]
174
+    }
175
+
176
+    public func index(after i: Int) -> Int {
177
+        return headers.index(after: i)
178
+    }
179
+}
180
+
181
+extension HTTPHeaders: CustomStringConvertible {
182
+    public var description: String {
183
+        return headers.map { $0.description }
184
+            .joined(separator: "\n")
185
+    }
186
+}
187
+
188
+// MARK: - HTTPHeader
189
+
190
+/// A representation of a single HTTP header's name / value pair.
191
+public struct HTTPHeader: Hashable {
192
+    /// Name of the header.
193
+    public let name: String
194
+
195
+    /// Value of the header.
196
+    public let value: String
197
+
198
+    /// Creates an instance from the given `name` and `value`.
199
+    ///
200
+    /// - Parameters:
201
+    ///   - name:  The name of the header.
202
+    ///   - value: The value of the header.
203
+    public init(name: String, value: String) {
204
+        self.name = name
205
+        self.value = value
206
+    }
207
+}
208
+
209
+extension HTTPHeader: CustomStringConvertible {
210
+    public var description: String {
211
+        return "\(name): \(value)"
212
+    }
213
+}
214
+
215
+extension HTTPHeader {
216
+    /// Returns an `Accept` header.
217
+    ///
218
+    /// - Parameter value: The `Accept` value.
219
+    /// - Returns:         The header.
220
+    public static func accept(_ value: String) -> HTTPHeader {
221
+        return HTTPHeader(name: "Accept", value: value)
222
+    }
223
+
224
+    /// Returns an `Accept-Charset` header.
225
+    ///
226
+    /// - Parameter value: The `Accept-Charset` value.
227
+    /// - Returns:         The header.
228
+    public static func acceptCharset(_ value: String) -> HTTPHeader {
229
+        return HTTPHeader(name: "Accept-Charset", value: value)
230
+    }
231
+
232
+    /// Returns an `Accept-Language` header.
233
+    ///
234
+    /// Alamofire offers a default Accept-Language header that accumulates and encodes the system's preferred languages.
235
+    /// Use `HTTPHeader.defaultAcceptLanguage`.
236
+    ///
237
+    /// - Parameter value: The `Accept-Language` value.
238
+    ///
239
+    /// - Returns:         The header.
240
+    public static func acceptLanguage(_ value: String) -> HTTPHeader {
241
+        return HTTPHeader(name: "Accept-Language", value: value)
242
+    }
243
+
244
+    /// Returns an `Accept-Encoding` header.
245
+    ///
246
+    /// Alamofire offers a default accept encoding value that provides the most common values. Use
247
+    /// `HTTPHeader.defaultAcceptEncoding`.
248
+    ///
249
+    /// - Parameter value: The `Accept-Encoding` value.
250
+    ///
251
+    /// - Returns:         The header
252
+    public static func acceptEncoding(_ value: String) -> HTTPHeader {
253
+        return HTTPHeader(name: "Accept-Encoding", value: value)
254
+    }
255
+
256
+    /// Returns a `Basic` `Authorization` header using the `username` and `password` provided.
257
+    ///
258
+    /// - Parameters:
259
+    ///   - username: The username of the header.
260
+    ///   - password: The password of the header.
261
+    ///
262
+    /// - Returns:    The header.
263
+    public static func authorization(username: String, password: String) -> HTTPHeader {
264
+        let credential = Data("\(username):\(password)".utf8).base64EncodedString()
265
+
266
+        return authorization("Basic \(credential)")
267
+    }
268
+
269
+    /// Returns a `Bearer` `Authorization` header using the `bearerToken` provided
270
+    ///
271
+    /// - Parameter bearerToken: The bearer token.
272
+    ///
273
+    /// - Returns:               The header.
274
+    public static func authorization(bearerToken: String) -> HTTPHeader {
275
+        return authorization("Bearer \(bearerToken)")
276
+    }
277
+
278
+    /// Returns an `Authorization` header.
279
+    ///
280
+    /// Alamofire provides built-in methods to produce `Authorization` headers. For a Basic `Authorization` header use
281
+    /// `HTTPHeader.authorization(username:password:)`. For a Bearer `Authorization` header, use
282
+    /// `HTTPHeader.authorization(bearerToken:)`.
283
+    ///
284
+    /// - Parameter value: The `Authorization` value.
285
+    ///
286
+    /// - Returns:         The header.
287
+    public static func authorization(_ value: String) -> HTTPHeader {
288
+        return HTTPHeader(name: "Authorization", value: value)
289
+    }
290
+
291
+    /// Returns a `Content-Disposition` header.
292
+    ///
293
+    /// - Parameter value: The `Content-Disposition` value.
294
+    ///
295
+    /// - Returns:         The header.
296
+    public static func contentDisposition(_ value: String) -> HTTPHeader {
297
+        return HTTPHeader(name: "Content-Disposition", value: value)
298
+    }
299
+
300
+    /// Returns a `Content-Type` header.
301
+    ///
302
+    /// All Alamofire `ParameterEncoding`s and `ParameterEncoder`s set the `Content-Type` of the request, so it may not be necessary to manually
303
+    /// set this value.
304
+    ///
305
+    /// - Parameter value: The `Content-Type` value.
306
+    ///
307
+    /// - Returns:         The header.
308
+    public static func contentType(_ value: String) -> HTTPHeader {
309
+        return HTTPHeader(name: "Content-Type", value: value)
310
+    }
311
+
312
+    /// Returns a `User-Agent` header.
313
+    ///
314
+    /// - Parameter value: The `User-Agent` value.
315
+    ///
316
+    /// - Returns:         The header.
317
+    public static func userAgent(_ value: String) -> HTTPHeader {
318
+        return HTTPHeader(name: "User-Agent", value: value)
319
+    }
320
+}
321
+
322
+extension Array where Element == HTTPHeader {
323
+    /// Case-insensitively finds the index of an `HTTPHeader` with the provided name, if it exists.
324
+    func index(of name: String) -> Int? {
325
+        let lowercasedName = name.lowercased()
326
+        return firstIndex { $0.name.lowercased() == lowercasedName }
327
+    }
328
+}
329
+
330
+// MARK: - Defaults
331
+
332
+public extension HTTPHeaders {
333
+    /// The default set of `HTTPHeaders` used by Alamofire. Includes `Accept-Encoding`, `Accept-Language`, and
334
+    /// `User-Agent`.
335
+    static let `default`: HTTPHeaders = [.defaultAcceptEncoding,
336
+                                         .defaultAcceptLanguage,
337
+                                         .defaultUserAgent]
338
+}
339
+
340
+extension HTTPHeader {
341
+    /// Returns Alamofire's default `Accept-Encoding` header, appropriate for the encodings supported by particular OS
342
+    /// versions.
343
+    ///
344
+    /// See the [Accept-Encoding HTTP header documentation](https://tools.ietf.org/html/rfc7230#section-4.2.3) .
345
+    public static let defaultAcceptEncoding: HTTPHeader = {
346
+        let encodings: [String]
347
+        if #available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, *) {
348
+            encodings = ["br", "gzip", "deflate"]
349
+        } else {
350
+            encodings = ["gzip", "deflate"]
351
+        }
352
+
353
+        return .acceptEncoding(encodings.qualityEncoded())
354
+    }()
355
+
356
+    /// Returns Alamofire's default `Accept-Language` header, generated by querying `Locale` for the user's
357
+    /// `preferredLanguages`.
358
+    ///
359
+    /// See the [Accept-Language HTTP header documentation](https://tools.ietf.org/html/rfc7231#section-5.3.5).
360
+    public static let defaultAcceptLanguage: HTTPHeader = {
361
+        .acceptLanguage(Locale.preferredLanguages.prefix(6).qualityEncoded())
362
+    }()
363
+
364
+    /// Returns Alamofire's default `User-Agent` header.
365
+    ///
366
+    /// See the [User-Agent header documentation](https://tools.ietf.org/html/rfc7231#section-5.5.3).
367
+    ///
368
+    /// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 13.0.0) Alamofire/5.0.0`
369
+    public static let defaultUserAgent: HTTPHeader = {
370
+        let userAgent: String = {
371
+            if let info = Bundle.main.infoDictionary {
372
+                let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
373
+                let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
374
+                let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
375
+                let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
376
+
377
+                let osNameVersion: String = {
378
+                    let version = ProcessInfo.processInfo.operatingSystemVersion
379
+                    let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
380
+                    // swiftformat:disable indent
381
+                    let osName: String = {
382
+                    #if os(iOS)
383
+                        return "iOS"
384
+                    #elseif os(watchOS)
385
+                        return "watchOS"
386
+                    #elseif os(tvOS)
387
+                        return "tvOS"
388
+                    #elseif os(macOS)
389
+                        return "macOS"
390
+                    #elseif os(Linux)
391
+                        return "Linux"
392
+                    #else
393
+                        return "Unknown"
394
+                    #endif
395
+                    }()
396
+                    // swiftformat:enable indent
397
+
398
+                    return "\(osName) \(versionString)"
399
+                }()
400
+
401
+                let alamofireVersion = "Alamofire/\(AF.version)"
402
+
403
+                return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
404
+            }
405
+
406
+            return "Alamofire"
407
+        }()
408
+
409
+        return .userAgent(userAgent)
410
+    }()
411
+}
412
+
413
+extension Collection where Element == String {
414
+    func qualityEncoded() -> String {
415
+        return enumerated().map { index, encoding in
416
+            let quality = 1.0 - (Double(index) * 0.1)
417
+            return "\(encoding);q=\(quality)"
418
+        }.joined(separator: ", ")
419
+    }
420
+}
421
+
422
+// MARK: - System Type Extensions
423
+
424
+extension URLRequest {
425
+    /// Returns `allHTTPHeaderFields` as `HTTPHeaders`.
426
+    public var headers: HTTPHeaders {
427
+        get { return allHTTPHeaderFields.map(HTTPHeaders.init) ?? HTTPHeaders() }
428
+        set { allHTTPHeaderFields = newValue.dictionary }
429
+    }
430
+}
431
+
432
+extension HTTPURLResponse {
433
+    /// Returns `allHeaderFields` as `HTTPHeaders`.
434
+    public var headers: HTTPHeaders {
435
+        return (allHeaderFields as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders()
436
+    }
437
+}
438
+
439
+public extension URLSessionConfiguration {
440
+    /// Returns `httpAdditionalHeaders` as `HTTPHeaders`.
441
+    var headers: HTTPHeaders {
442
+        get { return (httpAdditionalHeaders as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders() }
443
+        set { httpAdditionalHeaders = newValue.dictionary }
444
+    }
445
+}

+ 54
- 0
Pods/Alamofire/Source/HTTPMethod.swift View File

@@ -0,0 +1,54 @@
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
+    /// `TRACE` method.
47
+    public static let trace = HTTPMethod(rawValue: "TRACE")
48
+
49
+    public let rawValue: String
50
+
51
+    public init(rawValue: String) {
52
+        self.rawValue = rawValue
53
+    }
54
+}

+ 544
- 0
Pods/Alamofire/Source/MultipartFormData.swift View File

@@ -0,0 +1,544 @@
1
+//
2
+//  MultipartFormData.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
+#if os(iOS) || os(watchOS) || os(tvOS)
28
+import MobileCoreServices
29
+#elseif os(macOS)
30
+import CoreServices
31
+#endif
32
+
33
+/// Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode
34
+/// multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead
35
+/// to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the
36
+/// data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for
37
+/// larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset.
38
+///
39
+/// For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well
40
+/// and the w3 form documentation.
41
+///
42
+/// - https://www.ietf.org/rfc/rfc2388.txt
43
+/// - https://www.ietf.org/rfc/rfc2045.txt
44
+/// - https://www.w3.org/TR/html401/interact/forms.html#h-17.13
45
+open class MultipartFormData {
46
+    // MARK: - Helper Types
47
+
48
+    struct EncodingCharacters {
49
+        static let crlf = "\r\n"
50
+    }
51
+
52
+    struct BoundaryGenerator {
53
+        enum BoundaryType {
54
+            case initial, encapsulated, final
55
+        }
56
+
57
+        static func randomBoundary() -> String {
58
+            return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
59
+        }
60
+
61
+        static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data {
62
+            let boundaryText: String
63
+
64
+            switch boundaryType {
65
+            case .initial:
66
+                boundaryText = "--\(boundary)\(EncodingCharacters.crlf)"
67
+            case .encapsulated:
68
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)"
69
+            case .final:
70
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)"
71
+            }
72
+
73
+            return Data(boundaryText.utf8)
74
+        }
75
+    }
76
+
77
+    class BodyPart {
78
+        let headers: HTTPHeaders
79
+        let bodyStream: InputStream
80
+        let bodyContentLength: UInt64
81
+        var hasInitialBoundary = false
82
+        var hasFinalBoundary = false
83
+
84
+        init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) {
85
+            self.headers = headers
86
+            self.bodyStream = bodyStream
87
+            self.bodyContentLength = bodyContentLength
88
+        }
89
+    }
90
+
91
+    // MARK: - Properties
92
+
93
+    /// Default memory threshold used when encoding `MultipartFormData`, in bytes.
94
+    public static let encodingMemoryThreshold: UInt64 = 10_000_000
95
+
96
+    /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`.
97
+    open lazy var contentType: String = "multipart/form-data; boundary=\(self.boundary)"
98
+
99
+    /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries.
100
+    public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } }
101
+
102
+    /// The boundary used to separate the body parts in the encoded form data.
103
+    public let boundary: String
104
+
105
+    let fileManager: FileManager
106
+
107
+    private var bodyParts: [BodyPart]
108
+    private var bodyPartError: AFError?
109
+    private let streamBufferSize: Int
110
+
111
+    // MARK: - Lifecycle
112
+
113
+    /// Creates an instance.
114
+    ///
115
+    /// - Parameters:
116
+    ///   - fileManager: `FileManager` to use for file operations, if needed.
117
+    ///   - boundary: Boundary `String` used to separate body parts.
118
+    public init(fileManager: FileManager = .default, boundary: String? = nil) {
119
+        self.fileManager = fileManager
120
+        self.boundary = boundary ?? BoundaryGenerator.randomBoundary()
121
+        bodyParts = []
122
+
123
+        //
124
+        // The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more
125
+        // information, please refer to the following article:
126
+        //   - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html
127
+        //
128
+        streamBufferSize = 1024
129
+    }
130
+
131
+    // MARK: - Body Parts
132
+
133
+    /// Creates a body part from the data and appends it to the instance.
134
+    ///
135
+    /// The body part data will be encoded using the following format:
136
+    ///
137
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
138
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
139
+    /// - Encoded file data
140
+    /// - Multipart form boundary
141
+    ///
142
+    /// - Parameters:
143
+    ///   - data:     `Data` to encoding into the instance.
144
+    ///   - name:     Name to associate with the `Data` in the `Content-Disposition` HTTP header.
145
+    ///   - fileName: Filename to associate with the `Data` in the `Content-Disposition` HTTP header.
146
+    ///   - mimeType: MIME type to associate with the data in the `Content-Type` HTTP header.
147
+    public func append(_ data: Data, withName name: String, fileName: String? = nil, mimeType: String? = nil) {
148
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
149
+        let stream = InputStream(data: data)
150
+        let length = UInt64(data.count)
151
+
152
+        append(stream, withLength: length, headers: headers)
153
+    }
154
+
155
+    /// Creates a body part from the file and appends it to the instance.
156
+    ///
157
+    /// The body part data will be encoded using the following format:
158
+    ///
159
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header)
160
+    /// - `Content-Type: #{generated mimeType}` (HTTP Header)
161
+    /// - Encoded file data
162
+    /// - Multipart form boundary
163
+    ///
164
+    /// The filename in the `Content-Disposition` HTTP header is generated from the last path component of the
165
+    /// `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the
166
+    /// system associated MIME type.
167
+    ///
168
+    /// - Parameters:
169
+    ///   - fileURL: `URL` of the file whose content will be encoded into the instance.
170
+    ///   - name:    Name to associate with the file content in the `Content-Disposition` HTTP header.
171
+    public func append(_ fileURL: URL, withName name: String) {
172
+        let fileName = fileURL.lastPathComponent
173
+        let pathExtension = fileURL.pathExtension
174
+
175
+        if !fileName.isEmpty && !pathExtension.isEmpty {
176
+            let mime = mimeType(forPathExtension: pathExtension)
177
+            append(fileURL, withName: name, fileName: fileName, mimeType: mime)
178
+        } else {
179
+            setBodyPartError(withReason: .bodyPartFilenameInvalid(in: fileURL))
180
+        }
181
+    }
182
+
183
+    /// Creates a body part from the file and appends it to the instance.
184
+    ///
185
+    /// The body part data will be encoded using the following format:
186
+    ///
187
+    /// - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header)
188
+    /// - Content-Type: #{mimeType} (HTTP Header)
189
+    /// - Encoded file data
190
+    /// - Multipart form boundary
191
+    ///
192
+    /// - Parameters:
193
+    ///   - fileURL:  `URL` of the file whose content will be encoded into the instance.
194
+    ///   - name:     Name to associate with the file content in the `Content-Disposition` HTTP header.
195
+    ///   - fileName: Filename to associate with the file content in the `Content-Disposition` HTTP header.
196
+    ///   - mimeType: MIME type to associate with the file content in the `Content-Type` HTTP header.
197
+    public func append(_ fileURL: URL, withName name: String, fileName: String, mimeType: String) {
198
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
199
+
200
+        //============================================================
201
+        //                 Check 1 - is file URL?
202
+        //============================================================
203
+
204
+        guard fileURL.isFileURL else {
205
+            setBodyPartError(withReason: .bodyPartURLInvalid(url: fileURL))
206
+            return
207
+        }
208
+
209
+        //============================================================
210
+        //              Check 2 - is file URL reachable?
211
+        //============================================================
212
+
213
+        do {
214
+            let isReachable = try fileURL.checkPromisedItemIsReachable()
215
+            guard isReachable else {
216
+                setBodyPartError(withReason: .bodyPartFileNotReachable(at: fileURL))
217
+                return
218
+            }
219
+        } catch {
220
+            setBodyPartError(withReason: .bodyPartFileNotReachableWithError(atURL: fileURL, error: error))
221
+            return
222
+        }
223
+
224
+        //============================================================
225
+        //            Check 3 - is file URL a directory?
226
+        //============================================================
227
+
228
+        var isDirectory: ObjCBool = false
229
+        let path = fileURL.path
230
+
231
+        guard fileManager.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else {
232
+            setBodyPartError(withReason: .bodyPartFileIsDirectory(at: fileURL))
233
+            return
234
+        }
235
+
236
+        //============================================================
237
+        //          Check 4 - can the file size be extracted?
238
+        //============================================================
239
+
240
+        let bodyContentLength: UInt64
241
+
242
+        do {
243
+            guard let fileSize = try fileManager.attributesOfItem(atPath: path)[.size] as? NSNumber else {
244
+                setBodyPartError(withReason: .bodyPartFileSizeNotAvailable(at: fileURL))
245
+                return
246
+            }
247
+
248
+            bodyContentLength = fileSize.uint64Value
249
+        } catch {
250
+            setBodyPartError(withReason: .bodyPartFileSizeQueryFailedWithError(forURL: fileURL, error: error))
251
+            return
252
+        }
253
+
254
+        //============================================================
255
+        //       Check 5 - can a stream be created from file URL?
256
+        //============================================================
257
+
258
+        guard let stream = InputStream(url: fileURL) else {
259
+            setBodyPartError(withReason: .bodyPartInputStreamCreationFailed(for: fileURL))
260
+            return
261
+        }
262
+
263
+        append(stream, withLength: bodyContentLength, headers: headers)
264
+    }
265
+
266
+    /// Creates a body part from the stream and appends it to the instance.
267
+    ///
268
+    /// The body part data will be encoded using the following format:
269
+    ///
270
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
271
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
272
+    /// - Encoded stream data
273
+    /// - Multipart form boundary
274
+    ///
275
+    /// - Parameters:
276
+    ///   - stream:   `InputStream` to encode into the instance.
277
+    ///   - length:   Length, in bytes, of the stream.
278
+    ///   - name:     Name to associate with the stream content in the `Content-Disposition` HTTP header.
279
+    ///   - fileName: Filename to associate with the stream content in the `Content-Disposition` HTTP header.
280
+    ///   - mimeType: MIME type to associate with the stream content in the `Content-Type` HTTP header.
281
+    public func append(_ stream: InputStream,
282
+                       withLength length: UInt64,
283
+                       name: String,
284
+                       fileName: String,
285
+                       mimeType: String) {
286
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
287
+        append(stream, withLength: length, headers: headers)
288
+    }
289
+
290
+    /// Creates a body part with the stream, length, and headers and appends it to the instance.
291
+    ///
292
+    /// The body part data will be encoded using the following format:
293
+    ///
294
+    /// - HTTP headers
295
+    /// - Encoded stream data
296
+    /// - Multipart form boundary
297
+    ///
298
+    /// - Parameters:
299
+    ///   - stream:  `InputStream` to encode into the instance.
300
+    ///   - length:  Length, in bytes, of the stream.
301
+    ///   - headers: `HTTPHeaders` for the body part.
302
+    public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) {
303
+        let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
304
+        bodyParts.append(bodyPart)
305
+    }
306
+
307
+    // MARK: - Data Encoding
308
+
309
+    /// Encodes all appended body parts into a single `Data` value.
310
+    ///
311
+    /// - Note: This method will load all the appended body parts into memory all at the same time. This method should
312
+    ///         only be used when the encoded data will have a small memory footprint. For large data cases, please use
313
+    ///         the `writeEncodedData(to:))` method.
314
+    ///
315
+    /// - Returns: The encoded `Data`, if encoding is successful.
316
+    /// - Throws:  An `AFError` if encoding encounters an error.
317
+    public func encode() throws -> Data {
318
+        if let bodyPartError = bodyPartError {
319
+            throw bodyPartError
320
+        }
321
+
322
+        var encoded = Data()
323
+
324
+        bodyParts.first?.hasInitialBoundary = true
325
+        bodyParts.last?.hasFinalBoundary = true
326
+
327
+        for bodyPart in bodyParts {
328
+            let encodedData = try encode(bodyPart)
329
+            encoded.append(encodedData)
330
+        }
331
+
332
+        return encoded
333
+    }
334
+
335
+    /// Writes all appended body parts to the given file `URL`.
336
+    ///
337
+    /// This process is facilitated by reading and writing with input and output streams, respectively. Thus,
338
+    /// this approach is very memory efficient and should be used for large body part data.
339
+    ///
340
+    /// - Parameter fileURL: File `URL` to which to write the form data.
341
+    /// - Throws:            An `AFError` if encoding encounters an error.
342
+    public func writeEncodedData(to fileURL: URL) throws {
343
+        if let bodyPartError = bodyPartError {
344
+            throw bodyPartError
345
+        }
346
+
347
+        if fileManager.fileExists(atPath: fileURL.path) {
348
+            throw AFError.multipartEncodingFailed(reason: .outputStreamFileAlreadyExists(at: fileURL))
349
+        } else if !fileURL.isFileURL {
350
+            throw AFError.multipartEncodingFailed(reason: .outputStreamURLInvalid(url: fileURL))
351
+        }
352
+
353
+        guard let outputStream = OutputStream(url: fileURL, append: false) else {
354
+            throw AFError.multipartEncodingFailed(reason: .outputStreamCreationFailed(for: fileURL))
355
+        }
356
+
357
+        outputStream.open()
358
+        defer { outputStream.close() }
359
+
360
+        bodyParts.first?.hasInitialBoundary = true
361
+        bodyParts.last?.hasFinalBoundary = true
362
+
363
+        for bodyPart in bodyParts {
364
+            try write(bodyPart, to: outputStream)
365
+        }
366
+    }
367
+
368
+    // MARK: - Private - Body Part Encoding
369
+
370
+    private func encode(_ bodyPart: BodyPart) throws -> Data {
371
+        var encoded = Data()
372
+
373
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
374
+        encoded.append(initialData)
375
+
376
+        let headerData = encodeHeaders(for: bodyPart)
377
+        encoded.append(headerData)
378
+
379
+        let bodyStreamData = try encodeBodyStream(for: bodyPart)
380
+        encoded.append(bodyStreamData)
381
+
382
+        if bodyPart.hasFinalBoundary {
383
+            encoded.append(finalBoundaryData())
384
+        }
385
+
386
+        return encoded
387
+    }
388
+
389
+    private func encodeHeaders(for bodyPart: BodyPart) -> Data {
390
+        let headerText = bodyPart.headers.map { "\($0.name): \($0.value)\(EncodingCharacters.crlf)" }
391
+            .joined()
392
+            + EncodingCharacters.crlf
393
+
394
+        return Data(headerText.utf8)
395
+    }
396
+
397
+    private func encodeBodyStream(for bodyPart: BodyPart) throws -> Data {
398
+        let inputStream = bodyPart.bodyStream
399
+        inputStream.open()
400
+        defer { inputStream.close() }
401
+
402
+        var encoded = Data()
403
+
404
+        while inputStream.hasBytesAvailable {
405
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
406
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
407
+
408
+            if let error = inputStream.streamError {
409
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: error))
410
+            }
411
+
412
+            if bytesRead > 0 {
413
+                encoded.append(buffer, count: bytesRead)
414
+            } else {
415
+                break
416
+            }
417
+        }
418
+
419
+        return encoded
420
+    }
421
+
422
+    // MARK: - Private - Writing Body Part to Output Stream
423
+
424
+    private func write(_ bodyPart: BodyPart, to outputStream: OutputStream) throws {
425
+        try writeInitialBoundaryData(for: bodyPart, to: outputStream)
426
+        try writeHeaderData(for: bodyPart, to: outputStream)
427
+        try writeBodyStream(for: bodyPart, to: outputStream)
428
+        try writeFinalBoundaryData(for: bodyPart, to: outputStream)
429
+    }
430
+
431
+    private func writeInitialBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
432
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
433
+        return try write(initialData, to: outputStream)
434
+    }
435
+
436
+    private func writeHeaderData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
437
+        let headerData = encodeHeaders(for: bodyPart)
438
+        return try write(headerData, to: outputStream)
439
+    }
440
+
441
+    private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
442
+        let inputStream = bodyPart.bodyStream
443
+
444
+        inputStream.open()
445
+        defer { inputStream.close() }
446
+
447
+        while inputStream.hasBytesAvailable {
448
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
449
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
450
+
451
+            if let streamError = inputStream.streamError {
452
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
453
+            }
454
+
455
+            if bytesRead > 0 {
456
+                if buffer.count != bytesRead {
457
+                    buffer = Array(buffer[0..<bytesRead])
458
+                }
459
+
460
+                try write(&buffer, to: outputStream)
461
+            } else {
462
+                break
463
+            }
464
+        }
465
+    }
466
+
467
+    private func writeFinalBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
468
+        if bodyPart.hasFinalBoundary {
469
+            return try write(finalBoundaryData(), to: outputStream)
470
+        }
471
+    }
472
+
473
+    // MARK: - Private - Writing Buffered Data to Output Stream
474
+
475
+    private func write(_ data: Data, to outputStream: OutputStream) throws {
476
+        var buffer = [UInt8](repeating: 0, count: data.count)
477
+        data.copyBytes(to: &buffer, count: data.count)
478
+
479
+        return try write(&buffer, to: outputStream)
480
+    }
481
+
482
+    private func write(_ buffer: inout [UInt8], to outputStream: OutputStream) throws {
483
+        var bytesToWrite = buffer.count
484
+
485
+        while bytesToWrite > 0, outputStream.hasSpaceAvailable {
486
+            let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite)
487
+
488
+            if let error = outputStream.streamError {
489
+                throw AFError.multipartEncodingFailed(reason: .outputStreamWriteFailed(error: error))
490
+            }
491
+
492
+            bytesToWrite -= bytesWritten
493
+
494
+            if bytesToWrite > 0 {
495
+                buffer = Array(buffer[bytesWritten..<buffer.count])
496
+            }
497
+        }
498
+    }
499
+
500
+    // MARK: - Private - Mime Type
501
+
502
+    private func mimeType(forPathExtension pathExtension: String) -> String {
503
+        if
504
+            let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
505
+            let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() {
506
+            return contentType as String
507
+        }
508
+
509
+        return "application/octet-stream"
510
+    }
511
+
512
+    // MARK: - Private - Content Headers
513
+
514
+    private func contentHeaders(withName name: String, fileName: String? = nil, mimeType: String? = nil) -> HTTPHeaders {
515
+        var disposition = "form-data; name=\"\(name)\""
516
+        if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" }
517
+
518
+        var headers: HTTPHeaders = [.contentDisposition(disposition)]
519
+        if let mimeType = mimeType { headers.add(.contentType(mimeType)) }
520
+
521
+        return headers
522
+    }
523
+
524
+    // MARK: - Private - Boundary Encoding
525
+
526
+    private func initialBoundaryData() -> Data {
527
+        return BoundaryGenerator.boundaryData(forBoundaryType: .initial, boundary: boundary)
528
+    }
529
+
530
+    private func encapsulatedBoundaryData() -> Data {
531
+        return BoundaryGenerator.boundaryData(forBoundaryType: .encapsulated, boundary: boundary)
532
+    }
533
+
534
+    private func finalBoundaryData() -> Data {
535
+        return BoundaryGenerator.boundaryData(forBoundaryType: .final, boundary: boundary)
536
+    }
537
+
538
+    // MARK: - Private - Errors
539
+
540
+    private func setBodyPartError(withReason reason: AFError.MultipartEncodingFailureReason) {
541
+        guard bodyPartError == nil else { return }
542
+        bodyPartError = AFError.multipartEncodingFailed(reason: reason)
543
+    }
544
+}

+ 87
- 0
Pods/Alamofire/Source/MultipartUpload.swift View File

@@ -0,0 +1,87 @@
1
+//
2
+//  MultipartUpload.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
+/// Internal type which encapsulates a `MultipartFormData` upload.
28
+final class MultipartUpload {
29
+    lazy var result = Result { try build() }
30
+
31
+    let isInBackgroundSession: Bool
32
+    let multipartFormData: MultipartFormData
33
+    let encodingMemoryThreshold: UInt64
34
+    let request: URLRequestConvertible
35
+    let fileManager: FileManager
36
+
37
+    init(isInBackgroundSession: Bool,
38
+         encodingMemoryThreshold: UInt64,
39
+         request: URLRequestConvertible,
40
+         multipartFormData: MultipartFormData) {
41
+        self.isInBackgroundSession = isInBackgroundSession
42
+        self.encodingMemoryThreshold = encodingMemoryThreshold
43
+        self.request = request
44
+        fileManager = multipartFormData.fileManager
45
+        self.multipartFormData = multipartFormData
46
+    }
47
+
48
+    func build() throws -> (request: URLRequest, uploadable: UploadRequest.Uploadable) {
49
+        var urlRequest = try request.asURLRequest()
50
+        urlRequest.setValue(multipartFormData.contentType, forHTTPHeaderField: "Content-Type")
51
+
52
+        let uploadable: UploadRequest.Uploadable
53
+        if multipartFormData.contentLength < encodingMemoryThreshold && !isInBackgroundSession {
54
+            let data = try multipartFormData.encode()
55
+
56
+            uploadable = .data(data)
57
+        } else {
58
+            let tempDirectoryURL = fileManager.temporaryDirectory
59
+            let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data")
60
+            let fileName = UUID().uuidString
61
+            let fileURL = directoryURL.appendingPathComponent(fileName)
62
+
63
+            try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
64
+
65
+            do {
66
+                try multipartFormData.writeEncodedData(to: fileURL)
67
+            } catch {
68
+                // Cleanup after attempted write if it fails.
69
+                try? fileManager.removeItem(at: fileURL)
70
+            }
71
+
72
+            uploadable = .file(fileURL, shouldRemove: true)
73
+        }
74
+
75
+        return (request: urlRequest, uploadable: uploadable)
76
+    }
77
+}
78
+
79
+extension MultipartUpload: UploadConvertible {
80
+    func asURLRequest() throws -> URLRequest {
81
+        return try result.get().request
82
+    }
83
+
84
+    func createUploadable() throws -> UploadRequest.Uploadable {
85
+        return try result.get().uploadable
86
+    }
87
+}

+ 266
- 0
Pods/Alamofire/Source/NetworkReachabilityManager.swift View File

@@ -0,0 +1,266 @@
1
+//
2
+//  NetworkReachabilityManager.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
+#if !(os(watchOS) || os(Linux))
26
+
27
+import Foundation
28
+import SystemConfiguration
29
+
30
+/// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both cellular and
31
+/// WiFi network interfaces.
32
+///
33
+/// Reachability can be used to determine background information about why a network operation failed, or to retry
34
+/// network requests when a connection is established. It should not be used to prevent a user from initiating a network
35
+/// request, as it's possible that an initial request may be required to establish reachability.
36
+open class NetworkReachabilityManager {
37
+    /// Defines the various states of network reachability.
38
+    public enum NetworkReachabilityStatus {
39
+        /// It is unknown whether the network is reachable.
40
+        case unknown
41
+        /// The network is not reachable.
42
+        case notReachable
43
+        /// The network is reachable on the associated `ConnectionType`.
44
+        case reachable(ConnectionType)
45
+
46
+        init(_ flags: SCNetworkReachabilityFlags) {
47
+            guard flags.isActuallyReachable else { self = .notReachable; return }
48
+
49
+            var networkStatus: NetworkReachabilityStatus = .reachable(.ethernetOrWiFi)
50
+
51
+            if flags.isCellular { networkStatus = .reachable(.cellular) }
52
+
53
+            self = networkStatus
54
+        }
55
+
56
+        /// Defines the various connection types detected by reachability flags.
57
+        public enum ConnectionType {
58
+            /// The connection type is either over Ethernet or WiFi.
59
+            case ethernetOrWiFi
60
+            /// The connection type is a cellular connection.
61
+            case cellular
62
+        }
63
+    }
64
+
65
+    /// A closure executed when the network reachability status changes. The closure takes a single argument: the
66
+    /// network reachability status.
67
+    public typealias Listener = (NetworkReachabilityStatus) -> Void
68
+
69
+    /// Default `NetworkReachabilityManager` for the zero address and a `listenerQueue` of `.main`.
70
+    public static let `default` = NetworkReachabilityManager()
71
+
72
+    // MARK: - Properties
73
+
74
+    /// Whether the network is currently reachable.
75
+    open var isReachable: Bool { return isReachableOnCellular || isReachableOnEthernetOrWiFi }
76
+
77
+    /// Whether the network is currently reachable over the cellular interface.
78
+    ///
79
+    /// - Note: Using this property to decide whether to make a high or low bandwidth request is not recommended.
80
+    ///         Instead, set the `allowsCellularAccess` on any `URLRequest`s being issued.
81
+    ///
82
+    open var isReachableOnCellular: Bool { return status == .reachable(.cellular) }
83
+
84
+    /// Whether the network is currently reachable over Ethernet or WiFi interface.
85
+    open var isReachableOnEthernetOrWiFi: Bool { return status == .reachable(.ethernetOrWiFi) }
86
+
87
+    /// `DispatchQueue` on which reachability will update.
88
+    public let reachabilityQueue = DispatchQueue(label: "org.alamofire.reachabilityQueue")
89
+
90
+    /// Flags of the current reachability type, if any.
91
+    open var flags: SCNetworkReachabilityFlags? {
92
+        var flags = SCNetworkReachabilityFlags()
93
+
94
+        return (SCNetworkReachabilityGetFlags(reachability, &flags)) ? flags : nil
95
+    }
96
+
97
+    /// The current network reachability status.
98
+    open var status: NetworkReachabilityStatus {
99
+        return flags.map(NetworkReachabilityStatus.init) ?? .unknown
100
+    }
101
+
102
+    /// Mutable state storage.
103
+    struct MutableState {
104
+        /// A closure executed when the network reachability status changes.
105
+        var listener: Listener?
106
+        /// `DispatchQueue` on which listeners will be called.
107
+        var listenerQueue: DispatchQueue?
108
+        /// Previously calculated status.
109
+        var previousStatus: NetworkReachabilityStatus?
110
+    }
111
+
112
+    /// `SCNetworkReachability` instance providing notifications.
113
+    private let reachability: SCNetworkReachability
114
+
115
+    /// Protected storage for mutable state.
116
+    private let mutableState = Protector(MutableState())
117
+
118
+    // MARK: - Initialization
119
+
120
+    /// Creates an instance with the specified host.
121
+    ///
122
+    /// - Note: The `host` value must *not* contain a scheme, just the hostname.
123
+    ///
124
+    /// - Parameters:
125
+    ///   - host:          Host used to evaluate network reachability. Must *not* include the scheme (e.g. `https`).
126
+    public convenience init?(host: String) {
127
+        guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
128
+
129
+        self.init(reachability: reachability)
130
+    }
131
+
132
+    /// Creates an instance that monitors the address 0.0.0.0.
133
+    ///
134
+    /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing
135
+    /// status of the device, both IPv4 and IPv6.
136
+    public convenience init?() {
137
+        var zero = sockaddr()
138
+        zero.sa_len = UInt8(MemoryLayout<sockaddr>.size)
139
+        zero.sa_family = sa_family_t(AF_INET)
140
+
141
+        guard let reachability = SCNetworkReachabilityCreateWithAddress(nil, &zero) else { return nil }
142
+
143
+        self.init(reachability: reachability)
144
+    }
145
+
146
+    private init(reachability: SCNetworkReachability) {
147
+        self.reachability = reachability
148
+    }
149
+
150
+    deinit {
151
+        stopListening()
152
+    }
153
+
154
+    // MARK: - Listening
155
+
156
+    /// Starts listening for changes in network reachability status.
157
+    ///
158
+    /// - Note: Stops and removes any existing listener.
159
+    ///
160
+    /// - Parameters:
161
+    ///   - queue:    `DispatchQueue` on which to call the `listener` closure. `.main` by default.
162
+    ///   - listener: `Listener` closure called when reachability changes.
163
+    ///
164
+    /// - Returns: `true` if listening was started successfully, `false` otherwise.
165
+    @discardableResult
166
+    open func startListening(onQueue queue: DispatchQueue = .main,
167
+                             onUpdatePerforming listener: @escaping Listener) -> Bool {
168
+        stopListening()
169
+
170
+        mutableState.write { state in
171
+            state.listenerQueue = queue
172
+            state.listener = listener
173
+        }
174
+
175
+        var context = SCNetworkReachabilityContext(version: 0,
176
+                                                   info: Unmanaged.passRetained(self).toOpaque(),
177
+                                                   retain: nil,
178
+                                                   release: nil,
179
+                                                   copyDescription: nil)
180
+        let callback: SCNetworkReachabilityCallBack = { _, flags, info in
181
+            guard let info = info else { return }
182
+
183
+            let instance = Unmanaged<NetworkReachabilityManager>.fromOpaque(info).takeUnretainedValue()
184
+            instance.notifyListener(flags)
185
+        }
186
+
187
+        let queueAdded = SCNetworkReachabilitySetDispatchQueue(reachability, reachabilityQueue)
188
+        let callbackAdded = SCNetworkReachabilitySetCallback(reachability, callback, &context)
189
+
190
+        // Manually call listener to give initial state, since the framework may not.
191
+        if let currentFlags = flags {
192
+            reachabilityQueue.async {
193
+                self.notifyListener(currentFlags)
194
+            }
195
+        }
196
+
197
+        return callbackAdded && queueAdded
198
+    }
199
+
200
+    /// Stops listening for changes in network reachability status.
201
+    open func stopListening() {
202
+        SCNetworkReachabilitySetCallback(reachability, nil, nil)
203
+        SCNetworkReachabilitySetDispatchQueue(reachability, nil)
204
+        mutableState.write { state in
205
+            state.listener = nil
206
+            state.listenerQueue = nil
207
+            state.previousStatus = nil
208
+        }
209
+    }
210
+
211
+    // MARK: - Internal - Listener Notification
212
+
213
+    /// Calls the `listener` closure of the `listenerQueue` if the computed status hasn't changed.
214
+    ///
215
+    /// - Note: Should only be called from the `reachabilityQueue`.
216
+    ///
217
+    /// - Parameter flags: `SCNetworkReachabilityFlags` to use to calculate the status.
218
+    func notifyListener(_ flags: SCNetworkReachabilityFlags) {
219
+        let newStatus = NetworkReachabilityStatus(flags)
220
+
221
+        mutableState.write { state in
222
+            guard state.previousStatus != newStatus else { return }
223
+
224
+            state.previousStatus = newStatus
225
+
226
+            let listener = state.listener
227
+            state.listenerQueue?.async { listener?(newStatus) }
228
+        }
229
+    }
230
+}
231
+
232
+// MARK: -
233
+
234
+extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
235
+
236
+extension SCNetworkReachabilityFlags {
237
+    var isReachable: Bool { return contains(.reachable) }
238
+    var isConnectionRequired: Bool { return contains(.connectionRequired) }
239
+    var canConnectAutomatically: Bool { return contains(.connectionOnDemand) || contains(.connectionOnTraffic) }
240
+    var canConnectWithoutUserInteraction: Bool { return canConnectAutomatically && !contains(.interventionRequired) }
241
+    var isActuallyReachable: Bool { return isReachable && (!isConnectionRequired || canConnectWithoutUserInteraction) }
242
+    var isCellular: Bool {
243
+#if os(iOS) || os(tvOS)
244
+        return contains(.isWWAN)
245
+#else
246
+        return false
247
+#endif
248
+    }
249
+
250
+    /// Human readable `String` for all states, to help with debugging.
251
+    var readableDescription: String {
252
+        let W = isCellular ? "W" : "-"
253
+        let R = isReachable ? "R" : "-"
254
+        let c = isConnectionRequired ? "c" : "-"
255
+        let t = contains(.transientConnection) ? "t" : "-"
256
+        let i = contains(.interventionRequired) ? "i" : "-"
257
+        let C = contains(.connectionOnTraffic) ? "C" : "-"
258
+        let D = contains(.connectionOnDemand) ? "D" : "-"
259
+        let l = contains(.isLocalAddress) ? "l" : "-"
260
+        let d = contains(.isDirect) ? "d" : "-"
261
+        let a = contains(.connectionAutomatic) ? "a" : "-"
262
+
263
+        return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)\(a)"
264
+    }
265
+}
266
+#endif

+ 115
- 0
Pods/Alamofire/Source/Notifications.swift View File

@@ -0,0 +1,115 @@
1
+//
2
+//  Notifications.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
+public extension Request {
28
+    /// Posted when a `Request` is resumed. The `Notification` contains the resumed `Request`.
29
+    static let didResumeNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResume")
30
+    /// Posted when a `Request` is suspended. The `Notification` contains the suspended `Request`.
31
+    static let didSuspendNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspend")
32
+    /// Posted when a `Request` is cancelled. The `Notification` contains the cancelled `Request`.
33
+    static let didCancelNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancel")
34
+    /// Posted when a `Request` is finished. The `Notification` contains the completed `Request`.
35
+    static let didFinishNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didFinish")
36
+
37
+    /// Posted when a `URLSessionTask` is resumed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
38
+    static let didResumeTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResumeTask")
39
+    /// Posted when a `URLSessionTask` is suspended. The `Notification` contains the `Request` associated with the `URLSessionTask`.
40
+    static let didSuspendTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspendTask")
41
+    /// Posted when a `URLSessionTask` is cancelled. The `Notification` contains the `Request` associated with the `URLSessionTask`.
42
+    static let didCancelTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancelTask")
43
+    /// Posted when a `URLSessionTask` is completed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
44
+    static let didCompleteTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCompleteTask")
45
+}
46
+
47
+// MARK: -
48
+
49
+extension Notification {
50
+    /// The `Request` contained by the instance's `userInfo`, `nil` otherwise.
51
+    public var request: Request? {
52
+        return userInfo?[String.requestKey] as? Request
53
+    }
54
+
55
+    /// Convenience initializer for a `Notification` containing a `Request` payload.
56
+    ///
57
+    /// - Parameters:
58
+    ///   - name:    The name of the notification.
59
+    ///   - request: The `Request` payload.
60
+    init(name: Notification.Name, request: Request) {
61
+        self.init(name: name, object: nil, userInfo: [String.requestKey: request])
62
+    }
63
+}
64
+
65
+extension NotificationCenter {
66
+    /// Convenience function for posting notifications with `Request` payloads.
67
+    ///
68
+    /// - Parameters:
69
+    ///   - name:    The name of the notification.
70
+    ///   - request: The `Request` payload.
71
+    func postNotification(named name: Notification.Name, with request: Request) {
72
+        let notification = Notification(name: name, request: request)
73
+        post(notification)
74
+    }
75
+}
76
+
77
+extension String {
78
+    /// User info dictionary key representing the `Request` associated with the notification.
79
+    fileprivate static let requestKey = "org.alamofire.notification.key.request"
80
+}
81
+
82
+/// `EventMonitor` that provides Alamofire's notifications.
83
+public final class AlamofireNotifications: EventMonitor {
84
+    public func requestDidResume(_ request: Request) {
85
+        NotificationCenter.default.postNotification(named: Request.didResumeNotification, with: request)
86
+    }
87
+
88
+    public func requestDidSuspend(_ request: Request) {
89
+        NotificationCenter.default.postNotification(named: Request.didSuspendNotification, with: request)
90
+    }
91
+
92
+    public func requestDidCancel(_ request: Request) {
93
+        NotificationCenter.default.postNotification(named: Request.didCancelNotification, with: request)
94
+    }
95
+
96
+    public func requestDidFinish(_ request: Request) {
97
+        NotificationCenter.default.postNotification(named: Request.didFinishNotification, with: request)
98
+    }
99
+
100
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
101
+        NotificationCenter.default.postNotification(named: Request.didResumeTaskNotification, with: request)
102
+    }
103
+
104
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
105
+        NotificationCenter.default.postNotification(named: Request.didSuspendTaskNotification, with: request)
106
+    }
107
+
108
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
109
+        NotificationCenter.default.postNotification(named: Request.didCancelTaskNotification, with: request)
110
+    }
111
+
112
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
113
+        NotificationCenter.default.postNotification(named: Request.didCompleteTaskNotification, with: request)
114
+    }
115
+}

+ 49
- 0
Pods/Alamofire/Source/OperationQueue+Alamofire.swift View File

@@ -0,0 +1,49 @@
1
+//
2
+//  OperationQueue+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 Foundation
26
+
27
+extension OperationQueue {
28
+    /// Creates an instance using the provided parameters.
29
+    ///
30
+    /// - Parameters:
31
+    ///   - qualityOfService:            `QualityOfService` to be applied to the queue. `.default` by default.
32
+    ///   - maxConcurrentOperationCount: Maximum concurrent operations.
33
+    ///                                  `OperationQueue.defaultMaxConcurrentOperationCount` by default.
34
+    ///   - underlyingQueue: Underlying  `DispatchQueue`. `nil` by default.
35
+    ///   - name:                        Name for the queue. `nil` by default.
36
+    ///   - startSuspended:              Whether the queue starts suspended. `false` by default.
37
+    convenience init(qualityOfService: QualityOfService = .default,
38
+                     maxConcurrentOperationCount: Int = OperationQueue.defaultMaxConcurrentOperationCount,
39
+                     underlyingQueue: DispatchQueue? = nil,
40
+                     name: String? = nil,
41
+                     startSuspended: Bool = false) {
42
+        self.init()
43
+        self.qualityOfService = qualityOfService
44
+        self.maxConcurrentOperationCount = maxConcurrentOperationCount
45
+        self.underlyingQueue = underlyingQueue
46
+        self.name = name
47
+        isSuspended = startSuspended
48
+    }
49
+}

+ 184
- 0
Pods/Alamofire/Source/ParameterEncoder.swift View File

@@ -0,0 +1,184 @@
1
+//
2
+//  ParameterEncoder.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
+/// A type that can encode any `Encodable` type into a `URLRequest`.
28
+public protocol ParameterEncoder {
29
+    /// Encode the provided `Encodable` parameters into `request`.
30
+    ///
31
+    /// - Parameters:
32
+    ///   - parameters: The `Encodable` parameter value.
33
+    ///   - request:    The `URLRequest` into which to encode the parameters.
34
+    ///
35
+    /// - Returns:      A `URLRequest` with the result of the encoding.
36
+    /// - Throws:       An `Error` when encoding fails. For Alamofire provided encoders, this will be an instance of
37
+    ///                 `AFError.parameterEncoderFailed` with an associated `ParameterEncoderFailureReason`.
38
+    func encode<Parameters: Encodable>(_ parameters: Parameters?, into request: URLRequest) throws -> URLRequest
39
+}
40
+
41
+/// A `ParameterEncoder` that encodes types as JSON body data.
42
+///
43
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it's set to `application/json`.
44
+open class JSONParameterEncoder: ParameterEncoder {
45
+    /// Returns an encoder with default parameters.
46
+    public static var `default`: JSONParameterEncoder { return JSONParameterEncoder() }
47
+
48
+    /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.prettyPrinted`.
49
+    public static var prettyPrinted: JSONParameterEncoder {
50
+        let encoder = JSONEncoder()
51
+        encoder.outputFormatting = .prettyPrinted
52
+
53
+        return JSONParameterEncoder(encoder: encoder)
54
+    }
55
+
56
+    /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.sortedKeys`.
57
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
58
+    public static var sortedKeys: JSONParameterEncoder {
59
+        let encoder = JSONEncoder()
60
+        encoder.outputFormatting = .sortedKeys
61
+
62
+        return JSONParameterEncoder(encoder: encoder)
63
+    }
64
+
65
+    /// `JSONEncoder` used to encode parameters.
66
+    public let encoder: JSONEncoder
67
+
68
+    /// Creates an instance with the provided `JSONEncoder`.
69
+    ///
70
+    /// - Parameter encoder: The `JSONEncoder`. `JSONEncoder()` by default.
71
+    public init(encoder: JSONEncoder = JSONEncoder()) {
72
+        self.encoder = encoder
73
+    }
74
+
75
+    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
76
+                                            into request: URLRequest) throws -> URLRequest {
77
+        guard let parameters = parameters else { return request }
78
+
79
+        var request = request
80
+
81
+        do {
82
+            let data = try encoder.encode(parameters)
83
+            request.httpBody = data
84
+            if request.headers["Content-Type"] == nil {
85
+                request.headers.update(.contentType("application/json"))
86
+            }
87
+        } catch {
88
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
89
+        }
90
+
91
+        return request
92
+    }
93
+}
94
+
95
+/// A `ParameterEncoder` that encodes types as URL-encoded query strings to be set on the URL or as body data, depending
96
+/// on the `Destination` set.
97
+///
98
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it will be set to
99
+/// `application/x-www-form-urlencoded; charset=utf-8`.
100
+///
101
+/// Encoding behavior can be customized by passing an instance of `URLEncodedFormEncoder` to the initializer.
102
+open class URLEncodedFormParameterEncoder: ParameterEncoder {
103
+    /// Defines where the URL-encoded string should be set for each `URLRequest`.
104
+    public enum Destination {
105
+        /// Applies the encoded query string to any existing query string for `.get`, `.head`, and `.delete` request.
106
+        /// Sets it to the `httpBody` for all other methods.
107
+        case methodDependent
108
+        /// Applies the encoded query string to any existing query string from the `URLRequest`.
109
+        case queryString
110
+        /// Applies the encoded query string to the `httpBody` of the `URLRequest`.
111
+        case httpBody
112
+
113
+        /// Determines whether the URL-encoded string should be applied to the `URLRequest`'s `url`.
114
+        ///
115
+        /// - Parameter method: The `HTTPMethod`.
116
+        ///
117
+        /// - Returns:          Whether the URL-encoded string should be applied to a `URL`.
118
+        func encodesParametersInURL(for method: HTTPMethod) -> Bool {
119
+            switch self {
120
+            case .methodDependent: return [.get, .head, .delete].contains(method)
121
+            case .queryString: return true
122
+            case .httpBody: return false
123
+            }
124
+        }
125
+    }
126
+
127
+    /// Returns an encoder with default parameters.
128
+    public static var `default`: URLEncodedFormParameterEncoder { return URLEncodedFormParameterEncoder() }
129
+
130
+    /// The `URLEncodedFormEncoder` to use.
131
+    public let encoder: URLEncodedFormEncoder
132
+
133
+    /// The `Destination` for the URL-encoded string.
134
+    public let destination: Destination
135
+
136
+    /// Creates an instance with the provided `URLEncodedFormEncoder` instance and `Destination` value.
137
+    ///
138
+    /// - Parameters:
139
+    ///   - encoder:     The `URLEncodedFormEncoder`. `URLEncodedFormEncoder()` by default.
140
+    ///   - destination: The `Destination`. `.methodDependent` by default.
141
+    public init(encoder: URLEncodedFormEncoder = URLEncodedFormEncoder(), destination: Destination = .methodDependent) {
142
+        self.encoder = encoder
143
+        self.destination = destination
144
+    }
145
+
146
+    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
147
+                                            into request: URLRequest) throws -> URLRequest {
148
+        guard let parameters = parameters else { return request }
149
+
150
+        var request = request
151
+
152
+        guard let url = request.url else {
153
+            throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
154
+        }
155
+
156
+        guard let method = request.method else {
157
+            let rawValue = request.method?.rawValue ?? "nil"
158
+            throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.httpMethod(rawValue: rawValue)))
159
+        }
160
+
161
+        if destination.encodesParametersInURL(for: method),
162
+            var components = URLComponents(url: url, resolvingAgainstBaseURL: false) {
163
+            let query: String = try Result<String, Error> { try encoder.encode(parameters) }
164
+                .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
165
+            let newQueryString = [components.percentEncodedQuery, query].compactMap { $0 }.joinedWithAmpersands()
166
+            components.percentEncodedQuery = newQueryString.isEmpty ? nil : newQueryString
167
+
168
+            guard let newURL = components.url else {
169
+                throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
170
+            }
171
+
172
+            request.url = newURL
173
+        } else {
174
+            if request.headers["Content-Type"] == nil {
175
+                request.headers.update(.contentType("application/x-www-form-urlencoded; charset=utf-8"))
176
+            }
177
+
178
+            request.httpBody = try Result<Data, Error> { try encoder.encode(parameters) }
179
+                .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
180
+        }
181
+
182
+        return request
183
+    }
184
+}

+ 314
- 0
Pods/Alamofire/Source/ParameterEncoding.swift View File

@@ -0,0 +1,314 @@
1
+//
2
+//  ParameterEncoding.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
+/// A dictionary of parameters to apply to a `URLRequest`.
28
+public typealias Parameters = [String: Any]
29
+
30
+/// A type used to define how a set of parameters are applied to a `URLRequest`.
31
+public protocol ParameterEncoding {
32
+    /// Creates a `URLRequest` by encoding parameters and applying them on the passed request.
33
+    ///
34
+    /// - Parameters:
35
+    ///   - urlRequest: `URLRequestConvertible` value onto which parameters will be encoded.
36
+    ///   - parameters: `Parameters` to encode onto the request.
37
+    ///
38
+    /// - Returns:      The encoded `URLRequest`.
39
+    /// - Throws:       Any `Error` produced during parameter encoding.
40
+    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
41
+}
42
+
43
+// MARK: -
44
+
45
+/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP
46
+/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as
47
+/// the HTTP body depends on the destination of the encoding.
48
+///
49
+/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to
50
+/// `application/x-www-form-urlencoded; charset=utf-8`.
51
+///
52
+/// There is no published specification for how to encode collection types. By default the convention of appending
53
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
54
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
55
+/// square brackets appended to array keys.
56
+///
57
+/// `BoolEncoding` can be used to configure how boolean values are encoded. The default behavior is to encode
58
+/// `true` as 1 and `false` as 0.
59
+public struct URLEncoding: ParameterEncoding {
60
+    // MARK: Helper Types
61
+
62
+    /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the
63
+    /// resulting URL request.
64
+    public enum Destination {
65
+        /// Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE` requests and
66
+        /// sets as the HTTP body for requests with any other HTTP method.
67
+        case methodDependent
68
+        /// Sets or appends encoded query string result to existing query string.
69
+        case queryString
70
+        /// Sets encoded query string result as the HTTP body of the URL request.
71
+        case httpBody
72
+
73
+        func encodesParametersInURL(for method: HTTPMethod) -> Bool {
74
+            switch self {
75
+            case .methodDependent: return [.get, .head, .delete].contains(method)
76
+            case .queryString: return true
77
+            case .httpBody: return false
78
+            }
79
+        }
80
+    }
81
+
82
+    /// Configures how `Array` parameters are encoded.
83
+    public enum ArrayEncoding {
84
+        /// An empty set of square brackets is appended to the key for every value. This is the default behavior.
85
+        case brackets
86
+        /// No brackets are appended. The key is encoded as is.
87
+        case noBrackets
88
+
89
+        func encode(key: String) -> String {
90
+            switch self {
91
+            case .brackets:
92
+                return "\(key)[]"
93
+            case .noBrackets:
94
+                return key
95
+            }
96
+        }
97
+    }
98
+
99
+    /// Configures how `Bool` parameters are encoded.
100
+    public enum BoolEncoding {
101
+        /// Encode `true` as `1` and `false` as `0`. This is the default behavior.
102
+        case numeric
103
+        /// Encode `true` and `false` as string literals.
104
+        case literal
105
+
106
+        func encode(value: Bool) -> String {
107
+            switch self {
108
+            case .numeric:
109
+                return value ? "1" : "0"
110
+            case .literal:
111
+                return value ? "true" : "false"
112
+            }
113
+        }
114
+    }
115
+
116
+    // MARK: Properties
117
+
118
+    /// Returns a default `URLEncoding` instance with a `.methodDependent` destination.
119
+    public static var `default`: URLEncoding { return URLEncoding() }
120
+
121
+    /// Returns a `URLEncoding` instance with a `.queryString` destination.
122
+    public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) }
123
+
124
+    /// Returns a `URLEncoding` instance with an `.httpBody` destination.
125
+    public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) }
126
+
127
+    /// The destination defining where the encoded query string is to be applied to the URL request.
128
+    public let destination: Destination
129
+
130
+    /// The encoding to use for `Array` parameters.
131
+    public let arrayEncoding: ArrayEncoding
132
+
133
+    /// The encoding to use for `Bool` parameters.
134
+    public let boolEncoding: BoolEncoding
135
+
136
+    // MARK: Initialization
137
+
138
+    /// Creates an instance using the specified parameters.
139
+    ///
140
+    /// - Parameters:
141
+    ///   - destination:   `Destination` defining where the encoded query string will be applied. `.methodDependent` by
142
+    ///                    default.
143
+    ///   - arrayEncoding: `ArrayEncoding` to use. `.brackets` by default.
144
+    ///   - boolEncoding:  `BoolEncoding` to use. `.numeric` by default.
145
+    public init(destination: Destination = .methodDependent,
146
+                arrayEncoding: ArrayEncoding = .brackets,
147
+                boolEncoding: BoolEncoding = .numeric) {
148
+        self.destination = destination
149
+        self.arrayEncoding = arrayEncoding
150
+        self.boolEncoding = boolEncoding
151
+    }
152
+
153
+    // MARK: Encoding
154
+
155
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
156
+        var urlRequest = try urlRequest.asURLRequest()
157
+
158
+        guard let parameters = parameters else { return urlRequest }
159
+
160
+        if let method = urlRequest.method, destination.encodesParametersInURL(for: method) {
161
+            guard let url = urlRequest.url else {
162
+                throw AFError.parameterEncodingFailed(reason: .missingURL)
163
+            }
164
+
165
+            if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
166
+                let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
167
+                urlComponents.percentEncodedQuery = percentEncodedQuery
168
+                urlRequest.url = urlComponents.url
169
+            }
170
+        } else {
171
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
172
+                urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
173
+            }
174
+
175
+            urlRequest.httpBody = Data(query(parameters).utf8)
176
+        }
177
+
178
+        return urlRequest
179
+    }
180
+
181
+    /// Creates a percent-escaped, URL encoded query string components from the given key-value pair recursively.
182
+    ///
183
+    /// - Parameters:
184
+    ///   - key:   Key of the query component.
185
+    ///   - value: Value of the query component.
186
+    ///
187
+    /// - Returns: The percent-escaped, URL encoded query string components.
188
+    public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
189
+        var components: [(String, String)] = []
190
+
191
+        if let dictionary = value as? [String: Any] {
192
+            for (nestedKey, value) in dictionary {
193
+                components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
194
+            }
195
+        } else if let array = value as? [Any] {
196
+            for value in array {
197
+                components += queryComponents(fromKey: arrayEncoding.encode(key: key), value: value)
198
+            }
199
+        } else if let value = value as? NSNumber {
200
+            if value.isBool {
201
+                components.append((escape(key), escape(boolEncoding.encode(value: value.boolValue))))
202
+            } else {
203
+                components.append((escape(key), escape("\(value)")))
204
+            }
205
+        } else if let bool = value as? Bool {
206
+            components.append((escape(key), escape(boolEncoding.encode(value: bool))))
207
+        } else {
208
+            components.append((escape(key), escape("\(value)")))
209
+        }
210
+
211
+        return components
212
+    }
213
+
214
+    /// Creates a percent-escaped string following RFC 3986 for a query string key or value.
215
+    ///
216
+    /// - Parameter string: `String` to be percent-escaped.
217
+    ///
218
+    /// - Returns:          The percent-escaped `String`.
219
+    public func escape(_ string: String) -> String {
220
+        return string.addingPercentEncoding(withAllowedCharacters: .afURLQueryAllowed) ?? string
221
+    }
222
+
223
+    private func query(_ parameters: [String: Any]) -> String {
224
+        var components: [(String, String)] = []
225
+
226
+        for key in parameters.keys.sorted(by: <) {
227
+            let value = parameters[key]!
228
+            components += queryComponents(fromKey: key, value: value)
229
+        }
230
+        return components.map { "\($0)=\($1)" }.joined(separator: "&")
231
+    }
232
+}
233
+
234
+// MARK: -
235
+
236
+/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the
237
+/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
238
+public struct JSONEncoding: ParameterEncoding {
239
+    // MARK: Properties
240
+
241
+    /// Returns a `JSONEncoding` instance with default writing options.
242
+    public static var `default`: JSONEncoding { return JSONEncoding() }
243
+
244
+    /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options.
245
+    public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) }
246
+
247
+    /// The options for writing the parameters as JSON data.
248
+    public let options: JSONSerialization.WritingOptions
249
+
250
+    // MARK: Initialization
251
+
252
+    /// Creates an instance using the specified `WritingOptions`.
253
+    ///
254
+    /// - Parameter options: `JSONSerialization.WritingOptions` to use.
255
+    public init(options: JSONSerialization.WritingOptions = []) {
256
+        self.options = options
257
+    }
258
+
259
+    // MARK: Encoding
260
+
261
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
262
+        var urlRequest = try urlRequest.asURLRequest()
263
+
264
+        guard let parameters = parameters else { return urlRequest }
265
+
266
+        do {
267
+            let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
268
+
269
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
270
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
271
+            }
272
+
273
+            urlRequest.httpBody = data
274
+        } catch {
275
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
276
+        }
277
+
278
+        return urlRequest
279
+    }
280
+
281
+    /// Encodes any JSON compatible object into a `URLRequest`.
282
+    ///
283
+    /// - Parameters:
284
+    ///   - urlRequest: `URLRequestConvertible` value into which the object will be encoded.
285
+    ///   - jsonObject: `Any` value (must be JSON compatible` to be encoded into the `URLRequest`. `nil` by default.
286
+    ///
287
+    /// - Returns:      The encoded `URLRequest`.
288
+    /// - Throws:       Any `Error` produced during encoding.
289
+    public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest {
290
+        var urlRequest = try urlRequest.asURLRequest()
291
+
292
+        guard let jsonObject = jsonObject else { return urlRequest }
293
+
294
+        do {
295
+            let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
296
+
297
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
298
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
299
+            }
300
+
301
+            urlRequest.httpBody = data
302
+        } catch {
303
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
304
+        }
305
+
306
+        return urlRequest
307
+    }
308
+}
309
+
310
+// MARK: -
311
+
312
+extension NSNumber {
313
+    fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }
314
+}

+ 167
- 0
Pods/Alamofire/Source/Protector.swift View File

@@ -0,0 +1,167 @@
1
+//
2
+//  Protector.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
+// MARK: -
28
+
29
+/// An `os_unfair_lock` wrapper.
30
+final class UnfairLock {
31
+    private let unfairLock: os_unfair_lock_t
32
+
33
+    init() {
34
+        unfairLock = .allocate(capacity: 1)
35
+        unfairLock.initialize(to: os_unfair_lock())
36
+    }
37
+
38
+    deinit {
39
+        unfairLock.deinitialize(count: 1)
40
+        unfairLock.deallocate()
41
+    }
42
+
43
+    private func lock() {
44
+        os_unfair_lock_lock(unfairLock)
45
+    }
46
+
47
+    private func unlock() {
48
+        os_unfair_lock_unlock(unfairLock)
49
+    }
50
+
51
+    /// Executes a closure returning a value while acquiring the lock.
52
+    ///
53
+    /// - Parameter closure: The closure to run.
54
+    ///
55
+    /// - Returns:           The value the closure generated.
56
+    func around<T>(_ closure: () -> T) -> T {
57
+        lock(); defer { unlock() }
58
+        return closure()
59
+    }
60
+
61
+    /// Execute a closure while acquiring the lock.
62
+    ///
63
+    /// - Parameter closure: The closure to run.
64
+    func around(_ closure: () -> Void) {
65
+        lock(); defer { unlock() }
66
+        return closure()
67
+    }
68
+}
69
+
70
+/// A thread-safe wrapper around a value.
71
+final class Protector<T> {
72
+    private let lock = UnfairLock()
73
+    private var value: T
74
+
75
+    init(_ value: T) {
76
+        self.value = value
77
+    }
78
+
79
+    /// The contained value. Unsafe for anything more than direct read or write.
80
+    var directValue: T {
81
+        get { return lock.around { value } }
82
+        set { lock.around { value = newValue } }
83
+    }
84
+
85
+    /// Synchronously read or transform the contained value.
86
+    ///
87
+    /// - Parameter closure: The closure to execute.
88
+    ///
89
+    /// - Returns:           The return value of the closure passed.
90
+    func read<U>(_ closure: (T) -> U) -> U {
91
+        return lock.around { closure(self.value) }
92
+    }
93
+
94
+    /// Synchronously modify the protected value.
95
+    ///
96
+    /// - Parameter closure: The closure to execute.
97
+    ///
98
+    /// - Returns:           The modified value.
99
+    @discardableResult
100
+    func write<U>(_ closure: (inout T) -> U) -> U {
101
+        return lock.around { closure(&self.value) }
102
+    }
103
+}
104
+
105
+extension Protector where T: RangeReplaceableCollection {
106
+    /// Adds a new element to the end of this protected collection.
107
+    ///
108
+    /// - Parameter newElement: The `Element` to append.
109
+    func append(_ newElement: T.Element) {
110
+        write { (ward: inout T) in
111
+            ward.append(newElement)
112
+        }
113
+    }
114
+
115
+    /// Adds the elements of a sequence to the end of this protected collection.
116
+    ///
117
+    /// - Parameter newElements: The `Sequence` to append.
118
+    func append<S: Sequence>(contentsOf newElements: S) where S.Element == T.Element {
119
+        write { (ward: inout T) in
120
+            ward.append(contentsOf: newElements)
121
+        }
122
+    }
123
+
124
+    /// Add the elements of a collection to the end of the protected collection.
125
+    ///
126
+    /// - Parameter newElements: The `Collection` to append.
127
+    func append<C: Collection>(contentsOf newElements: C) where C.Element == T.Element {
128
+        write { (ward: inout T) in
129
+            ward.append(contentsOf: newElements)
130
+        }
131
+    }
132
+}
133
+
134
+extension Protector where T == Data? {
135
+    /// Adds the contents of a `Data` value to the end of the protected `Data`.
136
+    ///
137
+    /// - Parameter data: The `Data` to be appended.
138
+    func append(_ data: Data) {
139
+        write { (ward: inout T) in
140
+            ward?.append(data)
141
+        }
142
+    }
143
+}
144
+
145
+extension Protector where T == Request.MutableState {
146
+    /// Attempts to transition to the passed `State`.
147
+    ///
148
+    /// - Parameter state: The `State` to attempt transition to.
149
+    ///
150
+    /// - Returns:         Whether the transition occurred.
151
+    func attemptToTransitionTo(_ state: Request.State) -> Bool {
152
+        return lock.around {
153
+            guard value.state.canTransitionTo(state) else { return false }
154
+
155
+            value.state = state
156
+
157
+            return true
158
+        }
159
+    }
160
+
161
+    /// Perform a closure while locked with the provided `Request.State`.
162
+    ///
163
+    /// - Parameter perform: The closure to perform while locked.
164
+    func withState(perform: (Request.State) -> Void) {
165
+        lock.around { perform(value.state) }
166
+    }
167
+}

+ 95
- 0
Pods/Alamofire/Source/RedirectHandler.swift View File

@@ -0,0 +1,95 @@
1
+//
2
+//  RedirectHandler.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
+/// A type that handles how an HTTP redirect response from a remote server should be redirected to the new request.
28
+public protocol RedirectHandler {
29
+    /// Determines how the HTTP redirect response should be redirected to the new request.
30
+    ///
31
+    /// The `completion` closure should be passed one of three possible options:
32
+    ///
33
+    ///   1. The new request specified by the redirect (this is the most common use case).
34
+    ///   2. A modified version of the new request (you may want to route it somewhere else).
35
+    ///   3. A `nil` value to deny the redirect request and return the body of the redirect response.
36
+    ///
37
+    /// - Parameters:
38
+    ///   - task:       The task whose request resulted in a redirect.
39
+    ///   - request:    The URL request object to the new location specified by the redirect response.
40
+    ///   - response:   The response containing the server's response to the original request.
41
+    ///   - completion: The closure to execute containing the new request, a modified request, or `nil`.
42
+    func task(_ task: URLSessionTask,
43
+              willBeRedirectedTo request: URLRequest,
44
+              for response: HTTPURLResponse,
45
+              completion: @escaping (URLRequest?) -> Void)
46
+}
47
+
48
+// MARK: -
49
+
50
+/// `Redirector` is a convenience `RedirectHandler` making it easy to follow, not follow, or modify a redirect.
51
+public struct Redirector {
52
+    /// Defines the behavior of the `Redirector` type.
53
+    public enum Behavior {
54
+        /// Follow the redirect as defined in the response.
55
+        case follow
56
+        /// Do not follow the redirect defined in the response.
57
+        case doNotFollow
58
+        /// Modify the redirect request defined in the response.
59
+        case modify((URLSessionTask, URLRequest, HTTPURLResponse) -> URLRequest?)
60
+    }
61
+
62
+    /// Returns a `Redirector` with a `.follow` `Behavior`.
63
+    public static let follow = Redirector(behavior: .follow)
64
+    /// Returns a `Redirector` with a `.doNotFollow` `Behavior`.
65
+    public static let doNotFollow = Redirector(behavior: .doNotFollow)
66
+
67
+    /// The `Behavior` of the `Redirector`.
68
+    public let behavior: Behavior
69
+
70
+    /// Creates a `Redirector` instance from the `Behavior`.
71
+    ///
72
+    /// - Parameter behavior: The `Behavior`.
73
+    public init(behavior: Behavior) {
74
+        self.behavior = behavior
75
+    }
76
+}
77
+
78
+// MARK: -
79
+
80
+extension Redirector: RedirectHandler {
81
+    public func task(_ task: URLSessionTask,
82
+                     willBeRedirectedTo request: URLRequest,
83
+                     for response: HTTPURLResponse,
84
+                     completion: @escaping (URLRequest?) -> Void) {
85
+        switch behavior {
86
+        case .follow:
87
+            completion(request)
88
+        case .doNotFollow:
89
+            completion(nil)
90
+        case let .modify(closure):
91
+            let request = closure(task, request, response)
92
+            completion(request)
93
+        }
94
+    }
95
+}

+ 1461
- 0
Pods/Alamofire/Source/Request.swift
File diff suppressed because it is too large
View File


+ 243
- 0
Pods/Alamofire/Source/RequestInterceptor.swift View File

@@ -0,0 +1,243 @@
1
+//
2
+//  RequestInterceptor.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 can inspect and optionally adapt a `URLRequest` in some manner if necessary.
28
+public protocol RequestAdapter {
29
+    /// Inspects and adapts the specified `URLRequest` in some manner and calls the completion handler with the Result.
30
+    ///
31
+    /// - Parameters:
32
+    ///   - urlRequest: The `URLRequest` to adapt.
33
+    ///   - session:    The `Session` that will execute the `URLRequest`.
34
+    ///   - completion: The completion handler that must be called when adaptation is complete.
35
+    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
36
+}
37
+
38
+// MARK: -
39
+
40
+/// Outcome of determination whether retry is necessary.
41
+public enum RetryResult {
42
+    /// Retry should be attempted immediately.
43
+    case retry
44
+    /// Retry should be attempted after the associated `TimeInterval`.
45
+    case retryWithDelay(TimeInterval)
46
+    /// Do not retry.
47
+    case doNotRetry
48
+    /// Do not retry due to the associated `AFError`.
49
+    case doNotRetryWithError(Error)
50
+}
51
+
52
+extension RetryResult {
53
+    var retryRequired: Bool {
54
+        switch self {
55
+        case .retry, .retryWithDelay: return true
56
+        default: return false
57
+        }
58
+    }
59
+
60
+    var delay: TimeInterval? {
61
+        switch self {
62
+        case let .retryWithDelay(delay): return delay
63
+        default: return nil
64
+        }
65
+    }
66
+
67
+    var error: Error? {
68
+        guard case let .doNotRetryWithError(error) = self else { return nil }
69
+        return error
70
+    }
71
+}
72
+
73
+/// A type that determines whether a request should be retried after being executed by the specified session manager
74
+/// and encountering an error.
75
+public protocol RequestRetrier {
76
+    /// Determines whether the `Request` should be retried by calling the `completion` closure.
77
+    ///
78
+    /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs
79
+    /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly
80
+    /// cleaned up after.
81
+    ///
82
+    /// - Parameters:
83
+    ///   - request:    `Request` that failed due to the provided `Error`.
84
+    ///   - session:    `Session` that produced the `Request`.
85
+    ///   - error:      `Error` encountered while executing the `Request`.
86
+    ///   - completion: Completion closure to be executed when a retry decision has been determined.
87
+    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
88
+}
89
+
90
+// MARK: -
91
+
92
+/// Type that provides both `RequestAdapter` and `RequestRetrier` functionality.
93
+public protocol RequestInterceptor: RequestAdapter, RequestRetrier {}
94
+
95
+extension RequestInterceptor {
96
+    public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
97
+        completion(.success(urlRequest))
98
+    }
99
+
100
+    public func retry(_ request: Request,
101
+                      for session: Session,
102
+                      dueTo error: Error,
103
+                      completion: @escaping (RetryResult) -> Void) {
104
+        completion(.doNotRetry)
105
+    }
106
+}
107
+
108
+/// `RequestAdapter` closure definition.
109
+public typealias AdaptHandler = (URLRequest, Session, _ completion: @escaping (Result<URLRequest, Error>) -> Void) -> Void
110
+/// `RequestRetrier` closure definition.
111
+public typealias RetryHandler = (Request, Session, Error, _ completion: @escaping (RetryResult) -> Void) -> Void
112
+
113
+// MARK: -
114
+
115
+/// Closure-based `RequestAdapter`.
116
+open class Adapter: RequestInterceptor {
117
+    private let adaptHandler: AdaptHandler
118
+
119
+    /// Creates an instance using the provided closure.
120
+    ///
121
+    /// - Parameter adaptHandler: `AdaptHandler` closure to be executed when handling request adaptation.
122
+    public init(_ adaptHandler: @escaping AdaptHandler) {
123
+        self.adaptHandler = adaptHandler
124
+    }
125
+
126
+    open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
127
+        adaptHandler(urlRequest, session, completion)
128
+    }
129
+}
130
+
131
+// MARK: -
132
+
133
+/// Closure-based `RequestRetrier`.
134
+open class Retrier: RequestInterceptor {
135
+    private let retryHandler: RetryHandler
136
+
137
+    /// Creates an instance using the provided closure.
138
+    ///
139
+    /// - Parameter retryHandler: `RetryHandler` closure to be executed when handling request retry.
140
+    public init(_ retryHandler: @escaping RetryHandler) {
141
+        self.retryHandler = retryHandler
142
+    }
143
+
144
+    open func retry(_ request: Request,
145
+                    for session: Session,
146
+                    dueTo error: Error,
147
+                    completion: @escaping (RetryResult) -> Void) {
148
+        retryHandler(request, session, error, completion)
149
+    }
150
+}
151
+
152
+// MARK: -
153
+
154
+/// `RequestInterceptor` which can use multiple `RequestAdapter` and `RequestRetrier` values.
155
+open class Interceptor: RequestInterceptor {
156
+    /// All `RequestAdapter`s associated with the instance. These adapters will be run until one fails.
157
+    public let adapters: [RequestAdapter]
158
+    /// All `RequestRetrier`s associated with the instance. These retriers will be run one at a time until one triggers retry.
159
+    public let retriers: [RequestRetrier]
160
+
161
+    /// Creates an instance from `AdaptHandler` and `RetryHandler` closures.
162
+    ///
163
+    /// - Parameters:
164
+    ///   - adaptHandler: `AdaptHandler` closure to be used.
165
+    ///   - retryHandler: `RetryHandler` closure to be used.
166
+    public init(adaptHandler: @escaping AdaptHandler, retryHandler: @escaping RetryHandler) {
167
+        adapters = [Adapter(adaptHandler)]
168
+        retriers = [Retrier(retryHandler)]
169
+    }
170
+
171
+    /// Creates an instance from `RequestAdapter` and `RequestRetrier` values.
172
+    ///
173
+    /// - Parameters:
174
+    ///   - adapter: `RequestAdapter` value to be used.
175
+    ///   - retrier: `RequestRetrier` value to be used.
176
+    public init(adapter: RequestAdapter, retrier: RequestRetrier) {
177
+        adapters = [adapter]
178
+        retriers = [retrier]
179
+    }
180
+
181
+    /// Creates an instance from the arrays of `RequestAdapter` and `RequestRetrier` values.
182
+    ///
183
+    /// - Parameters:
184
+    ///   - adapters: `RequestAdapter` values to be used.
185
+    ///   - retriers: `RequestRetrier` values to be used.
186
+    public init(adapters: [RequestAdapter] = [], retriers: [RequestRetrier] = []) {
187
+        self.adapters = adapters
188
+        self.retriers = retriers
189
+    }
190
+
191
+    open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
192
+        adapt(urlRequest, for: session, using: adapters, completion: completion)
193
+    }
194
+
195
+    private func adapt(_ urlRequest: URLRequest,
196
+                       for session: Session,
197
+                       using adapters: [RequestAdapter],
198
+                       completion: @escaping (Result<URLRequest, Error>) -> Void) {
199
+        var pendingAdapters = adapters
200
+
201
+        guard !pendingAdapters.isEmpty else { completion(.success(urlRequest)); return }
202
+
203
+        let adapter = pendingAdapters.removeFirst()
204
+
205
+        adapter.adapt(urlRequest, for: session) { result in
206
+            switch result {
207
+            case let .success(urlRequest):
208
+                self.adapt(urlRequest, for: session, using: pendingAdapters, completion: completion)
209
+            case .failure:
210
+                completion(result)
211
+            }
212
+        }
213
+    }
214
+
215
+    open func retry(_ request: Request,
216
+                    for session: Session,
217
+                    dueTo error: Error,
218
+                    completion: @escaping (RetryResult) -> Void) {
219
+        retry(request, for: session, dueTo: error, using: retriers, completion: completion)
220
+    }
221
+
222
+    private func retry(_ request: Request,
223
+                       for session: Session,
224
+                       dueTo error: Error,
225
+                       using retriers: [RequestRetrier],
226
+                       completion: @escaping (RetryResult) -> Void) {
227
+        var pendingRetriers = retriers
228
+
229
+        guard !pendingRetriers.isEmpty else { completion(.doNotRetry); return }
230
+
231
+        let retrier = pendingRetriers.removeFirst()
232
+
233
+        retrier.retry(request, for: session, dueTo: error) { result in
234
+            switch result {
235
+            case .retry, .retryWithDelay, .doNotRetryWithError:
236
+                completion(result)
237
+            case .doNotRetry:
238
+                // Only continue to the next retrier if retry was not triggered and no error was encountered
239
+                self.retry(request, for: session, dueTo: error, using: pendingRetriers, completion: completion)
240
+            }
241
+        }
242
+    }
243
+}

+ 136
- 0
Pods/Alamofire/Source/RequestTaskMap.swift View File

@@ -0,0 +1,136 @@
1
+//
2
+//  RequestTaskMap.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
+/// A type that maintains a two way, one to one map of `URLSessionTask`s to `Request`s.
28
+struct RequestTaskMap {
29
+    private var tasksToRequests: [URLSessionTask: Request]
30
+    private var requestsToTasks: [Request: URLSessionTask]
31
+    private var taskEvents: [URLSessionTask: (completed: Bool, metricsGathered: Bool)]
32
+
33
+    var requests: [Request] {
34
+        return Array(tasksToRequests.values)
35
+    }
36
+
37
+    init(tasksToRequests: [URLSessionTask: Request] = [:],
38
+         requestsToTasks: [Request: URLSessionTask] = [:],
39
+         taskEvents: [URLSessionTask: (completed: Bool, metricsGathered: Bool)] = [:]) {
40
+        self.tasksToRequests = tasksToRequests
41
+        self.requestsToTasks = requestsToTasks
42
+        self.taskEvents = taskEvents
43
+    }
44
+
45
+    subscript(_ request: Request) -> URLSessionTask? {
46
+        get { return requestsToTasks[request] }
47
+        set {
48
+            guard let newValue = newValue else {
49
+                guard let task = requestsToTasks[request] else {
50
+                    fatalError("RequestTaskMap consistency error: no task corresponding to request found.")
51
+                }
52
+
53
+                requestsToTasks.removeValue(forKey: request)
54
+                tasksToRequests.removeValue(forKey: task)
55
+                taskEvents.removeValue(forKey: task)
56
+
57
+                return
58
+            }
59
+
60
+            requestsToTasks[request] = newValue
61
+            tasksToRequests[newValue] = request
62
+            taskEvents[newValue] = (completed: false, metricsGathered: false)
63
+        }
64
+    }
65
+
66
+    subscript(_ task: URLSessionTask) -> Request? {
67
+        get { return tasksToRequests[task] }
68
+        set {
69
+            guard let newValue = newValue else {
70
+                guard let request = tasksToRequests[task] else {
71
+                    fatalError("RequestTaskMap consistency error: no request corresponding to task found.")
72
+                }
73
+
74
+                tasksToRequests.removeValue(forKey: task)
75
+                requestsToTasks.removeValue(forKey: request)
76
+                taskEvents.removeValue(forKey: task)
77
+
78
+                return
79
+            }
80
+
81
+            tasksToRequests[task] = newValue
82
+            requestsToTasks[newValue] = task
83
+            taskEvents[task] = (completed: false, metricsGathered: false)
84
+        }
85
+    }
86
+
87
+    var count: Int {
88
+        precondition(tasksToRequests.count == requestsToTasks.count,
89
+                     "RequestTaskMap.count invalid, requests.count: \(tasksToRequests.count) != tasks.count: \(requestsToTasks.count)")
90
+
91
+        return tasksToRequests.count
92
+    }
93
+
94
+    var eventCount: Int {
95
+        precondition(taskEvents.count == count, "RequestTaskMap.eventCount invalid, count: \(count) != taskEvents.count: \(taskEvents.count)")
96
+
97
+        return taskEvents.count
98
+    }
99
+
100
+    var isEmpty: Bool {
101
+        precondition(tasksToRequests.isEmpty == requestsToTasks.isEmpty,
102
+                     "RequestTaskMap.isEmpty invalid, requests.isEmpty: \(tasksToRequests.isEmpty) != tasks.isEmpty: \(requestsToTasks.isEmpty)")
103
+
104
+        return tasksToRequests.isEmpty
105
+    }
106
+
107
+    var isEventsEmpty: Bool {
108
+        precondition(taskEvents.isEmpty == isEmpty, "RequestTaskMap.isEventsEmpty invalid, isEmpty: \(isEmpty) != taskEvents.isEmpty: \(taskEvents.isEmpty)")
109
+
110
+        return taskEvents.isEmpty
111
+    }
112
+
113
+    mutating func disassociateIfNecessaryAfterGatheringMetricsForTask(_ task: URLSessionTask) {
114
+        guard let events = taskEvents[task] else {
115
+            fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
116
+        }
117
+
118
+        switch (events.completed, events.metricsGathered) {
119
+        case (_, true): fatalError("RequestTaskMap consistency error: duplicate metricsGatheredForTask call.")
120
+        case (false, false): taskEvents[task] = (completed: false, metricsGathered: true)
121
+        case (true, false): self[task] = nil
122
+        }
123
+    }
124
+
125
+    mutating func disassociateIfNecessaryAfterCompletingTask(_ task: URLSessionTask) {
126
+        guard let events = taskEvents[task] else {
127
+            fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
128
+        }
129
+
130
+        switch (events.completed, events.metricsGathered) {
131
+        case (true, _): fatalError("RequestTaskMap consistency error: duplicate completionReceivedForTask call.")
132
+        case (false, false): taskEvents[task] = (completed: true, metricsGathered: false)
133
+        case (false, true): self[task] = nil
134
+        }
135
+    }
136
+}

+ 399
- 0
Pods/Alamofire/Source/Response.swift View File

@@ -0,0 +1,399 @@
1
+//
2
+//  Response.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
+/// Default type of `DataResponse` returned by Alamofire, with an `AFError` `Failure` type.
28
+public typealias AFDataResponse<Success> = DataResponse<Success, AFError>
29
+/// Default type of `DownloadResponse` returned by Alamofire, with an `AFError` `Failure` type.
30
+public typealias AFDownloadResponse<Success> = DownloadResponse<Success, AFError>
31
+
32
+/// Type used to store all values associated with a serialized response of a `DataRequest` or `UploadRequest`.
33
+public struct DataResponse<Success, Failure: Error> {
34
+    /// The URL request sent to the server.
35
+    public let request: URLRequest?
36
+
37
+    /// The server's response to the URL request.
38
+    public let response: HTTPURLResponse?
39
+
40
+    /// The data returned by the server.
41
+    public let data: Data?
42
+
43
+    /// The final metrics of the response.
44
+    public let metrics: URLSessionTaskMetrics?
45
+
46
+    /// The time taken to serialize the response.
47
+    public let serializationDuration: TimeInterval
48
+
49
+    /// The result of response serialization.
50
+    public let result: Result<Success, Failure>
51
+
52
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
53
+    public var value: Success? { return result.success }
54
+
55
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
56
+    public var error: Failure? { return result.failure }
57
+
58
+    /// Creates a `DataResponse` instance with the specified parameters derived from the response serialization.
59
+    ///
60
+    /// - Parameters:
61
+    ///   - request:               The `URLRequest` sent to the server.
62
+    ///   - response:              The `HTTPURLResponse` from the server.
63
+    ///   - data:                  The `Data` returned by the server.
64
+    ///   - metrics:               The `URLSessionTaskMetrics` of the `DataRequest` or `UploadRequest`.
65
+    ///   - serializationDuration: The duration taken by serialization.
66
+    ///   - result:                The `Result` of response serialization.
67
+    public init(request: URLRequest?,
68
+                response: HTTPURLResponse?,
69
+                data: Data?,
70
+                metrics: URLSessionTaskMetrics?,
71
+                serializationDuration: TimeInterval,
72
+                result: Result<Success, Failure>) {
73
+        self.request = request
74
+        self.response = response
75
+        self.data = data
76
+        self.metrics = metrics
77
+        self.serializationDuration = serializationDuration
78
+        self.result = result
79
+    }
80
+}
81
+
82
+// MARK: -
83
+
84
+extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
85
+    /// The textual representation used when written to an output stream, which includes whether the result was a
86
+    /// success or failure.
87
+    public var description: String {
88
+        return "\(result)"
89
+    }
90
+
91
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
92
+    /// response, the server data, the duration of the network and serialization actions, and the response serialization
93
+    /// result.
94
+    public var debugDescription: String {
95
+        let requestDescription = request.map { "\($0.httpMethod!) \($0)" } ?? "nil"
96
+        let requestBody = request?.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "None"
97
+        let responseDescription = response.map { response in
98
+            let sortedHeaders = response.headers.sorted()
99
+
100
+            return """
101
+            [Status Code]: \(response.statusCode)
102
+            [Headers]:
103
+            \(sortedHeaders)
104
+            """
105
+        } ?? "nil"
106
+        let responseBody = data.map { String(decoding: $0, as: UTF8.self) } ?? "None"
107
+        let metricsDescription = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
108
+
109
+        return """
110
+        [Request]: \(requestDescription)
111
+        [Request Body]: \n\(requestBody)
112
+        [Response]: \n\(responseDescription)
113
+        [Response Body]: \n\(responseBody)
114
+        [Data]: \(data?.description ?? "None")
115
+        [Network Duration]: \(metricsDescription)
116
+        [Serialization Duration]: \(serializationDuration)s
117
+        [Result]: \(result)
118
+        """
119
+    }
120
+}
121
+
122
+// MARK: -
123
+
124
+extension DataResponse {
125
+    /// Evaluates the specified closure when the result of this `DataResponse` is a success, passing the unwrapped
126
+    /// result value as a parameter.
127
+    ///
128
+    /// Use the `map` method with a closure that does not throw. For example:
129
+    ///
130
+    ///     let possibleData: DataResponse<Data> = ...
131
+    ///     let possibleInt = possibleData.map { $0.count }
132
+    ///
133
+    /// - parameter transform: A closure that takes the success value of the instance's result.
134
+    ///
135
+    /// - returns: A `DataResponse` whose result wraps the value returned by the given closure. If this instance's
136
+    ///            result is a failure, returns a response wrapping the same failure.
137
+    public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> DataResponse<NewSuccess, Failure> {
138
+        return DataResponse<NewSuccess, Failure>(request: request,
139
+                                                 response: response,
140
+                                                 data: data,
141
+                                                 metrics: metrics,
142
+                                                 serializationDuration: serializationDuration,
143
+                                                 result: result.map(transform))
144
+    }
145
+
146
+    /// Evaluates the given closure when the result of this `DataResponse` is a success, passing the unwrapped result
147
+    /// value as a parameter.
148
+    ///
149
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
150
+    ///
151
+    ///     let possibleData: DataResponse<Data> = ...
152
+    ///     let possibleObject = possibleData.tryMap {
153
+    ///         try JSONSerialization.jsonObject(with: $0)
154
+    ///     }
155
+    ///
156
+    /// - parameter transform: A closure that takes the success value of the instance's result.
157
+    ///
158
+    /// - returns: A success or failure `DataResponse` depending on the result of the given closure. If this instance's
159
+    ///            result is a failure, returns the same failure.
160
+    public func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> DataResponse<NewSuccess, Error> {
161
+        return DataResponse<NewSuccess, Error>(request: request,
162
+                                               response: response,
163
+                                               data: data,
164
+                                               metrics: metrics,
165
+                                               serializationDuration: serializationDuration,
166
+                                               result: result.tryMap(transform))
167
+    }
168
+
169
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
170
+    ///
171
+    /// Use the `mapError` function with a closure that does not throw. For example:
172
+    ///
173
+    ///     let possibleData: DataResponse<Data> = ...
174
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
175
+    ///
176
+    /// - Parameter transform: A closure that takes the error of the instance.
177
+    ///
178
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
179
+    public func mapError<NewFailure: Error>(_ transform: (Failure) -> NewFailure) -> DataResponse<Success, NewFailure> {
180
+        return DataResponse<Success, NewFailure>(request: request,
181
+                                                 response: response,
182
+                                                 data: data,
183
+                                                 metrics: metrics,
184
+                                                 serializationDuration: serializationDuration,
185
+                                                 result: result.mapError(transform))
186
+    }
187
+
188
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
189
+    ///
190
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
191
+    ///
192
+    ///     let possibleData: DataResponse<Data> = ...
193
+    ///     let possibleObject = possibleData.tryMapError {
194
+    ///         try someFailableFunction(taking: $0)
195
+    ///     }
196
+    ///
197
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
198
+    ///
199
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
200
+    public func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> DataResponse<Success, Error> {
201
+        return DataResponse<Success, Error>(request: request,
202
+                                            response: response,
203
+                                            data: data,
204
+                                            metrics: metrics,
205
+                                            serializationDuration: serializationDuration,
206
+                                            result: result.tryMapError(transform))
207
+    }
208
+}
209
+
210
+// MARK: -
211
+
212
+/// Used to store all data associated with a serialized response of a download request.
213
+public struct DownloadResponse<Success, Failure: Error> {
214
+    /// The URL request sent to the server.
215
+    public let request: URLRequest?
216
+
217
+    /// The server's response to the URL request.
218
+    public let response: HTTPURLResponse?
219
+
220
+    /// The final destination URL of the data returned from the server after it is moved.
221
+    public let fileURL: URL?
222
+
223
+    /// The resume data generated if the request was cancelled.
224
+    public let resumeData: Data?
225
+
226
+    /// The final metrics of the response.
227
+    public let metrics: URLSessionTaskMetrics?
228
+
229
+    /// The time taken to serialize the response.
230
+    public let serializationDuration: TimeInterval
231
+
232
+    /// The result of response serialization.
233
+    public let result: Result<Success, Failure>
234
+
235
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
236
+    public var value: Success? { return result.success }
237
+
238
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
239
+    public var error: Failure? { return result.failure }
240
+
241
+    /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization.
242
+    ///
243
+    /// - Parameters:
244
+    ///   - request:               The `URLRequest` sent to the server.
245
+    ///   - response:              The `HTTPURLResponse` from the server.
246
+    ///   - temporaryURL:          The temporary destination `URL` of the data returned from the server.
247
+    ///   - destinationURL:        The final destination `URL` of the data returned from the server, if it was moved.
248
+    ///   - resumeData:            The resume `Data` generated if the request was cancelled.
249
+    ///   - metrics:               The `URLSessionTaskMetrics` of the `DownloadRequest`.
250
+    ///   - serializationDuration: The duration taken by serialization.
251
+    ///   - result:                The `Result` of response serialization.
252
+    public init(request: URLRequest?,
253
+                response: HTTPURLResponse?,
254
+                fileURL: URL?,
255
+                resumeData: Data?,
256
+                metrics: URLSessionTaskMetrics?,
257
+                serializationDuration: TimeInterval,
258
+                result: Result<Success, Failure>) {
259
+        self.request = request
260
+        self.response = response
261
+        self.fileURL = fileURL
262
+        self.resumeData = resumeData
263
+        self.metrics = metrics
264
+        self.serializationDuration = serializationDuration
265
+        self.result = result
266
+    }
267
+}
268
+
269
+// MARK: -
270
+
271
+extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible {
272
+    /// The textual representation used when written to an output stream, which includes whether the result was a
273
+    /// success or failure.
274
+    public var description: String {
275
+        return "\(result)"
276
+    }
277
+
278
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
279
+    /// response, the temporary and destination URLs, the resume data, the durations of the network and serialization
280
+    /// actions, and the response serialization result.
281
+    public var debugDescription: String {
282
+        let requestDescription = request.map { "\($0.httpMethod!) \($0)" } ?? "nil"
283
+        let requestBody = request?.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "None"
284
+        let responseDescription = response.map { response in
285
+            let sortedHeaders = response.headers.sorted()
286
+
287
+            return """
288
+            [Status Code]: \(response.statusCode)
289
+            [Headers]:
290
+            \(sortedHeaders)
291
+            """
292
+        } ?? "nil"
293
+        let metricsDescription = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
294
+        let resumeDataDescription = resumeData.map { "\($0)" } ?? "None"
295
+
296
+        return """
297
+        [Request]: \(requestDescription)
298
+        [Request Body]: \n\(requestBody)
299
+        [Response]: \n\(responseDescription)
300
+        [File URL]: \(fileURL?.path ?? "nil")
301
+        [ResumeData]: \(resumeDataDescription)
302
+        [Network Duration]: \(metricsDescription)
303
+        [Serialization Duration]: \(serializationDuration)s
304
+        [Result]: \(result)
305
+        """
306
+    }
307
+}
308
+
309
+// MARK: -
310
+
311
+extension DownloadResponse {
312
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
313
+    /// result value as a parameter.
314
+    ///
315
+    /// Use the `map` method with a closure that does not throw. For example:
316
+    ///
317
+    ///     let possibleData: DownloadResponse<Data> = ...
318
+    ///     let possibleInt = possibleData.map { $0.count }
319
+    ///
320
+    /// - parameter transform: A closure that takes the success value of the instance's result.
321
+    ///
322
+    /// - returns: A `DownloadResponse` whose result wraps the value returned by the given closure. If this instance's
323
+    ///            result is a failure, returns a response wrapping the same failure.
324
+    public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> DownloadResponse<NewSuccess, Failure> {
325
+        return DownloadResponse<NewSuccess, Failure>(request: request,
326
+                                                     response: response,
327
+                                                     fileURL: fileURL,
328
+                                                     resumeData: resumeData,
329
+                                                     metrics: metrics,
330
+                                                     serializationDuration: serializationDuration,
331
+                                                     result: result.map(transform))
332
+    }
333
+
334
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
335
+    /// result value as a parameter.
336
+    ///
337
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
338
+    ///
339
+    ///     let possibleData: DownloadResponse<Data> = ...
340
+    ///     let possibleObject = possibleData.tryMap {
341
+    ///         try JSONSerialization.jsonObject(with: $0)
342
+    ///     }
343
+    ///
344
+    /// - parameter transform: A closure that takes the success value of the instance's result.
345
+    ///
346
+    /// - returns: A success or failure `DownloadResponse` depending on the result of the given closure. If this
347
+    /// instance's result is a failure, returns the same failure.
348
+    public func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> DownloadResponse<NewSuccess, Error> {
349
+        return DownloadResponse<NewSuccess, Error>(request: request,
350
+                                                   response: response,
351
+                                                   fileURL: fileURL,
352
+                                                   resumeData: resumeData,
353
+                                                   metrics: metrics,
354
+                                                   serializationDuration: serializationDuration,
355
+                                                   result: result.tryMap(transform))
356
+    }
357
+
358
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
359
+    ///
360
+    /// Use the `mapError` function with a closure that does not throw. For example:
361
+    ///
362
+    ///     let possibleData: DownloadResponse<Data> = ...
363
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
364
+    ///
365
+    /// - Parameter transform: A closure that takes the error of the instance.
366
+    ///
367
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
368
+    public func mapError<NewFailure: Error>(_ transform: (Failure) -> NewFailure) -> DownloadResponse<Success, NewFailure> {
369
+        return DownloadResponse<Success, NewFailure>(request: request,
370
+                                                     response: response,
371
+                                                     fileURL: fileURL,
372
+                                                     resumeData: resumeData,
373
+                                                     metrics: metrics,
374
+                                                     serializationDuration: serializationDuration,
375
+                                                     result: result.mapError(transform))
376
+    }
377
+
378
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
379
+    ///
380
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
381
+    ///
382
+    ///     let possibleData: DownloadResponse<Data> = ...
383
+    ///     let possibleObject = possibleData.tryMapError {
384
+    ///         try someFailableFunction(taking: $0)
385
+    ///     }
386
+    ///
387
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
388
+    ///
389
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
390
+    public func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> DownloadResponse<Success, Error> {
391
+        return DownloadResponse<Success, Error>(request: request,
392
+                                                response: response,
393
+                                                fileURL: fileURL,
394
+                                                resumeData: resumeData,
395
+                                                metrics: metrics,
396
+                                                serializationDuration: serializationDuration,
397
+                                                result: result.tryMapError(transform))
398
+    }
399
+}

+ 779
- 0
Pods/Alamofire/Source/ResponseSerialization.swift View File

@@ -0,0 +1,779 @@
1
+//
2
+//  ResponseSerialization.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
+// MARK: Protocols
28
+
29
+/// The type to which all data response serializers must conform in order to serialize a response.
30
+public protocol DataResponseSerializerProtocol {
31
+    /// The type of serialized object to be created.
32
+    associatedtype SerializedObject
33
+
34
+    /// Serialize the response `Data` into the provided type..
35
+    ///
36
+    /// - Parameters:
37
+    ///   - request:  `URLRequest` which was used to perform the request, if any.
38
+    ///   - response: `HTTPURLResponse` received from the server, if any.
39
+    ///   - data:     `Data` returned from the server, if any.
40
+    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
41
+    ///
42
+    /// - Returns:    The `SerializedObject`.
43
+    /// - Throws:     Any `Error` produced during serialization.
44
+    func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> SerializedObject
45
+}
46
+
47
+/// The type to which all download response serializers must conform in order to serialize a response.
48
+public protocol DownloadResponseSerializerProtocol {
49
+    /// The type of serialized object to be created.
50
+    associatedtype SerializedObject
51
+
52
+    /// Serialize the downloaded response `Data` from disk into the provided type..
53
+    ///
54
+    /// - Parameters:
55
+    ///   - request:  `URLRequest` which was used to perform the request, if any.
56
+    ///   - response: `HTTPURLResponse` received from the server, if any.
57
+    ///   - fileURL:  File `URL` to which the response data was downloaded.
58
+    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
59
+    ///
60
+    /// - Returns:    The `SerializedObject`.
61
+    /// - Throws:     Any `Error` produced during serialization.
62
+    func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> SerializedObject
63
+}
64
+
65
+/// A serializer that can handle both data and download responses.
66
+public protocol ResponseSerializer: DataResponseSerializerProtocol & DownloadResponseSerializerProtocol {
67
+    /// `DataPreprocessor` used to prepare incoming `Data` for serialization.
68
+    var dataPreprocessor: DataPreprocessor { get }
69
+    /// `HTTPMethod`s for which empty response bodies are considered appropriate.
70
+    var emptyRequestMethods: Set<HTTPMethod> { get }
71
+    /// HTTP response codes for which empty response bodies are considered appropriate.
72
+    var emptyResponseCodes: Set<Int> { get }
73
+}
74
+
75
+/// Type used to preprocess `Data` before it handled by a serializer.
76
+public protocol DataPreprocessor {
77
+    /// Process           `Data` before it's handled by a serializer.
78
+    /// - Parameter data: The raw `Data` to process.
79
+    func preprocess(_ data: Data) throws -> Data
80
+}
81
+
82
+/// `DataPreprocessor` that returns passed `Data` without any transform.
83
+public struct PassthroughPreprocessor: DataPreprocessor {
84
+    public init() {}
85
+
86
+    public func preprocess(_ data: Data) throws -> Data { return data }
87
+}
88
+
89
+/// `DataPreprocessor` that trims Google's typical `)]}',\n` XSSI JSON header.
90
+public struct GoogleXSSIPreprocessor: DataPreprocessor {
91
+    public init() {}
92
+
93
+    public func preprocess(_ data: Data) throws -> Data {
94
+        return (data.prefix(6) == Data(")]}',\n".utf8)) ? data.dropFirst(6) : data
95
+    }
96
+}
97
+
98
+extension ResponseSerializer {
99
+    /// Default `DataPreprocessor`. `PassthroughPreprocessor` by default.
100
+    public static var defaultDataPreprocessor: DataPreprocessor { return PassthroughPreprocessor() }
101
+    /// Default `HTTPMethod`s for which empty response bodies are considered appropriate. `[.head]` by default.
102
+    public static var defaultEmptyRequestMethods: Set<HTTPMethod> { return [.head] }
103
+    /// HTTP response codes for which empty response bodies are considered appropriate. `[204, 205]` by default.
104
+    public static var defaultEmptyResponseCodes: Set<Int> { return [204, 205] }
105
+
106
+    public var dataPreprocessor: DataPreprocessor { return Self.defaultDataPreprocessor }
107
+    public var emptyRequestMethods: Set<HTTPMethod> { return Self.defaultEmptyRequestMethods }
108
+    public var emptyResponseCodes: Set<Int> { return Self.defaultEmptyResponseCodes }
109
+
110
+    /// Determines whether the `request` allows empty response bodies, if `request` exists.
111
+    ///
112
+    /// - Parameter request: `URLRequest` to evaluate.
113
+    ///
114
+    /// - Returns:           `Bool` representing the outcome of the evaluation, or `nil` if `request` was `nil`.
115
+    public func requestAllowsEmptyResponseData(_ request: URLRequest?) -> Bool? {
116
+        return request.flatMap { $0.httpMethod }
117
+            .flatMap(HTTPMethod.init)
118
+            .map { emptyRequestMethods.contains($0) }
119
+    }
120
+
121
+    /// Determines whether the `response` allows empty response bodies, if `response` exists`.
122
+    ///
123
+    /// - Parameter response: `HTTPURLResponse` to evaluate.
124
+    ///
125
+    /// - Returns:            `Bool` representing the outcome of the evaluation, or `nil` if `response` was `nil`.
126
+    public func responseAllowsEmptyResponseData(_ response: HTTPURLResponse?) -> Bool? {
127
+        return response.flatMap { $0.statusCode }
128
+            .map { emptyResponseCodes.contains($0) }
129
+    }
130
+
131
+    /// Determines whether `request` and `response` allow empty response bodies.
132
+    ///
133
+    /// - Parameters:
134
+    ///   - request:  `URLRequest` to evaluate.
135
+    ///   - response: `HTTPURLResponse` to evaluate.
136
+    ///
137
+    /// - Returns:    `true` if `request` or `response` allow empty bodies, `false` otherwise.
138
+    public func emptyResponseAllowed(forRequest request: URLRequest?, response: HTTPURLResponse?) -> Bool {
139
+        return (requestAllowsEmptyResponseData(request) == true) || (responseAllowsEmptyResponseData(response) == true)
140
+    }
141
+}
142
+
143
+/// By default, any serializer declared to conform to both types will get file serialization for free, as it just feeds
144
+/// the data read from disk into the data response serializer.
145
+public extension DownloadResponseSerializerProtocol where Self: DataResponseSerializerProtocol {
146
+    func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> Self.SerializedObject {
147
+        guard error == nil else { throw error! }
148
+
149
+        guard let fileURL = fileURL else {
150
+            throw AFError.responseSerializationFailed(reason: .inputFileNil)
151
+        }
152
+
153
+        let data: Data
154
+        do {
155
+            data = try Data(contentsOf: fileURL)
156
+        } catch {
157
+            throw AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))
158
+        }
159
+
160
+        do {
161
+            return try serialize(request: request, response: response, data: data, error: error)
162
+        } catch {
163
+            throw error
164
+        }
165
+    }
166
+}
167
+
168
+// MARK: - Default
169
+
170
+extension DataRequest {
171
+    /// Adds a handler to be called once the request has finished.
172
+    ///
173
+    /// - Parameters:
174
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
175
+    ///   - completionHandler: The code to be executed once the request has finished.
176
+    ///
177
+    /// - Returns:             The request.
178
+    @discardableResult
179
+    public func response(queue: DispatchQueue = .main, completionHandler: @escaping (AFDataResponse<Data?>) -> Void) -> Self {
180
+        appendResponseSerializer {
181
+            // Start work that should be on the serialization queue.
182
+            let result = AFResult<Data?>(value: self.data, error: self.error)
183
+            // End work that should be on the serialization queue.
184
+
185
+            self.underlyingQueue.async {
186
+                let response = DataResponse(request: self.request,
187
+                                            response: self.response,
188
+                                            data: self.data,
189
+                                            metrics: self.metrics,
190
+                                            serializationDuration: 0,
191
+                                            result: result)
192
+
193
+                self.eventMonitor?.request(self, didParseResponse: response)
194
+
195
+                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
196
+            }
197
+        }
198
+
199
+        return self
200
+    }
201
+
202
+    /// Adds a handler to be called once the request has finished.
203
+    ///
204
+    /// - Parameters:
205
+    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default
206
+    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data.
207
+    ///   - completionHandler:  The code to be executed once the request has finished.
208
+    ///
209
+    /// - Returns:              The request.
210
+    @discardableResult
211
+    public func response<Serializer: DataResponseSerializerProtocol>(queue: DispatchQueue = .main,
212
+                                                                     responseSerializer: Serializer,
213
+                                                                     completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void)
214
+        -> Self {
215
+        appendResponseSerializer {
216
+            // Start work that should be on the serialization queue.
217
+            let start = CFAbsoluteTimeGetCurrent()
218
+            let result: AFResult<Serializer.SerializedObject> = Result {
219
+                try responseSerializer.serialize(request: self.request,
220
+                                                 response: self.response,
221
+                                                 data: self.data,
222
+                                                 error: self.error)
223
+            }.mapError { error in
224
+                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
225
+            }
226
+
227
+            let end = CFAbsoluteTimeGetCurrent()
228
+            // End work that should be on the serialization queue.
229
+
230
+            self.underlyingQueue.async {
231
+                let response = DataResponse(request: self.request,
232
+                                            response: self.response,
233
+                                            data: self.data,
234
+                                            metrics: self.metrics,
235
+                                            serializationDuration: end - start,
236
+                                            result: result)
237
+
238
+                self.eventMonitor?.request(self, didParseResponse: response)
239
+
240
+                guard let serializerError = result.failure, let delegate = self.delegate else {
241
+                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
242
+                    return
243
+                }
244
+
245
+                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
246
+                    var didComplete: (() -> Void)?
247
+
248
+                    defer {
249
+                        if let didComplete = didComplete {
250
+                            self.responseSerializerDidComplete { queue.async { didComplete() } }
251
+                        }
252
+                    }
253
+
254
+                    switch retryResult {
255
+                    case .doNotRetry:
256
+                        didComplete = { completionHandler(response) }
257
+
258
+                    case let .doNotRetryWithError(retryError):
259
+                        let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
260
+
261
+                        let response = DataResponse(request: self.request,
262
+                                                    response: self.response,
263
+                                                    data: self.data,
264
+                                                    metrics: self.metrics,
265
+                                                    serializationDuration: end - start,
266
+                                                    result: result)
267
+
268
+                        didComplete = { completionHandler(response) }
269
+
270
+                    case .retry, .retryWithDelay:
271
+                        delegate.retryRequest(self, withDelay: retryResult.delay)
272
+                    }
273
+                }
274
+            }
275
+        }
276
+
277
+        return self
278
+    }
279
+}
280
+
281
+extension DownloadRequest {
282
+    /// Adds a handler to be called once the request has finished.
283
+    ///
284
+    /// - Parameters:
285
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
286
+    ///   - completionHandler: The code to be executed once the request has finished.
287
+    ///
288
+    /// - Returns:             The request.
289
+    @discardableResult
290
+    public func response(queue: DispatchQueue = .main,
291
+                         completionHandler: @escaping (AFDownloadResponse<URL?>) -> Void)
292
+        -> Self {
293
+        appendResponseSerializer {
294
+            // Start work that should be on the serialization queue.
295
+            let result = AFResult<URL?>(value: self.fileURL, error: self.error)
296
+            // End work that should be on the serialization queue.
297
+
298
+            self.underlyingQueue.async {
299
+                let response = DownloadResponse(request: self.request,
300
+                                                response: self.response,
301
+                                                fileURL: self.fileURL,
302
+                                                resumeData: self.resumeData,
303
+                                                metrics: self.metrics,
304
+                                                serializationDuration: 0,
305
+                                                result: result)
306
+
307
+                self.eventMonitor?.request(self, didParseResponse: response)
308
+
309
+                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
310
+            }
311
+        }
312
+
313
+        return self
314
+    }
315
+
316
+    /// Adds a handler to be called once the request has finished.
317
+    ///
318
+    /// - Parameters:
319
+    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default.
320
+    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data
321
+    ///                         contained in the destination `URL`.
322
+    ///   - completionHandler:  The code to be executed once the request has finished.
323
+    ///
324
+    /// - Returns:              The request.
325
+    @discardableResult
326
+    public func response<T: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
327
+                                                                responseSerializer: T,
328
+                                                                completionHandler: @escaping (AFDownloadResponse<T.SerializedObject>) -> Void)
329
+        -> Self {
330
+        appendResponseSerializer {
331
+            // Start work that should be on the serialization queue.
332
+            let start = CFAbsoluteTimeGetCurrent()
333
+            let result: AFResult<T.SerializedObject> = Result {
334
+                try responseSerializer.serializeDownload(request: self.request,
335
+                                                         response: self.response,
336
+                                                         fileURL: self.fileURL,
337
+                                                         error: self.error)
338
+            }.mapError { error in
339
+                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
340
+            }
341
+            let end = CFAbsoluteTimeGetCurrent()
342
+            // End work that should be on the serialization queue.
343
+
344
+            self.underlyingQueue.async {
345
+                let response = DownloadResponse(request: self.request,
346
+                                                response: self.response,
347
+                                                fileURL: self.fileURL,
348
+                                                resumeData: self.resumeData,
349
+                                                metrics: self.metrics,
350
+                                                serializationDuration: end - start,
351
+                                                result: result)
352
+
353
+                self.eventMonitor?.request(self, didParseResponse: response)
354
+
355
+                guard let serializerError = result.failure, let delegate = self.delegate else {
356
+                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
357
+                    return
358
+                }
359
+
360
+                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
361
+                    var didComplete: (() -> Void)?
362
+
363
+                    defer {
364
+                        if let didComplete = didComplete {
365
+                            self.responseSerializerDidComplete { queue.async { didComplete() } }
366
+                        }
367
+                    }
368
+
369
+                    switch retryResult {
370
+                    case .doNotRetry:
371
+                        didComplete = { completionHandler(response) }
372
+
373
+                    case let .doNotRetryWithError(retryError):
374
+                        let result: AFResult<T.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
375
+
376
+                        let response = DownloadResponse(request: self.request,
377
+                                                        response: self.response,
378
+                                                        fileURL: self.fileURL,
379
+                                                        resumeData: self.resumeData,
380
+                                                        metrics: self.metrics,
381
+                                                        serializationDuration: end - start,
382
+                                                        result: result)
383
+
384
+                        didComplete = { completionHandler(response) }
385
+
386
+                    case .retry, .retryWithDelay:
387
+                        delegate.retryRequest(self, withDelay: retryResult.delay)
388
+                    }
389
+                }
390
+            }
391
+        }
392
+
393
+        return self
394
+    }
395
+}
396
+
397
+// MARK: - Data
398
+
399
+extension DataRequest {
400
+    /// Adds a handler to be called once the request has finished.
401
+    ///
402
+    /// - Parameters:
403
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
404
+    ///   - completionHandler: The code to be executed once the request has finished.
405
+    ///
406
+    /// - Returns:             The request.
407
+    @discardableResult
408
+    public func responseData(queue: DispatchQueue = .main,
409
+                             completionHandler: @escaping (AFDataResponse<Data>) -> Void)
410
+        -> Self {
411
+        return response(queue: queue,
412
+                        responseSerializer: DataResponseSerializer(),
413
+                        completionHandler: completionHandler)
414
+    }
415
+}
416
+
417
+/// A `ResponseSerializer` that performs minimal response checking and returns any response data as-is. By default, a
418
+/// request returning `nil` or no data is considered an error. However, if the response is has a status code valid for
419
+/// empty responses (`204`, `205`), then an empty `Data` value is returned.
420
+public final class DataResponseSerializer: ResponseSerializer {
421
+    public let dataPreprocessor: DataPreprocessor
422
+    public let emptyResponseCodes: Set<Int>
423
+    public let emptyRequestMethods: Set<HTTPMethod>
424
+
425
+    /// Creates an instance using the provided values.
426
+    ///
427
+    /// - Parameters:
428
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
429
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
430
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
431
+    public init(dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
432
+                emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
433
+                emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) {
434
+        self.dataPreprocessor = dataPreprocessor
435
+        self.emptyResponseCodes = emptyResponseCodes
436
+        self.emptyRequestMethods = emptyRequestMethods
437
+    }
438
+
439
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Data {
440
+        guard error == nil else { throw error! }
441
+
442
+        guard var data = data, !data.isEmpty else {
443
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
444
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
445
+            }
446
+
447
+            return Data()
448
+        }
449
+
450
+        data = try dataPreprocessor.preprocess(data)
451
+
452
+        return data
453
+    }
454
+}
455
+
456
+extension DownloadRequest {
457
+    /// Adds a handler to be called once the request has finished.
458
+    ///
459
+    /// - Parameters:
460
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
461
+    ///   - completionHandler: The code to be executed once the request has finished.
462
+    ///
463
+    /// - Returns:             The request.
464
+    @discardableResult
465
+    public func responseData(queue: DispatchQueue = .main,
466
+                             completionHandler: @escaping (AFDownloadResponse<Data>) -> Void)
467
+        -> Self {
468
+        return response(queue: queue,
469
+                        responseSerializer: DataResponseSerializer(),
470
+                        completionHandler: completionHandler)
471
+    }
472
+}
473
+
474
+// MARK: - String
475
+
476
+/// A `ResponseSerializer` that decodes the response data as a `String`. By default, a request returning `nil` or no
477
+/// data is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`),
478
+/// then an empty `String` is returned.
479
+public final class StringResponseSerializer: ResponseSerializer {
480
+    public let dataPreprocessor: DataPreprocessor
481
+    /// Optional string encoding used to validate the response.
482
+    public let encoding: String.Encoding?
483
+    public let emptyResponseCodes: Set<Int>
484
+    public let emptyRequestMethods: Set<HTTPMethod>
485
+
486
+    /// Creates an instance with the provided values.
487
+    ///
488
+    /// - Parameters:
489
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
490
+    ///   - encoding:            A string encoding. Defaults to `nil`, in which case the encoding will be determined
491
+    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
492
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
493
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
494
+    public init(dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
495
+                encoding: String.Encoding? = nil,
496
+                emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
497
+                emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) {
498
+        self.dataPreprocessor = dataPreprocessor
499
+        self.encoding = encoding
500
+        self.emptyResponseCodes = emptyResponseCodes
501
+        self.emptyRequestMethods = emptyRequestMethods
502
+    }
503
+
504
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> String {
505
+        guard error == nil else { throw error! }
506
+
507
+        guard var data = data, !data.isEmpty else {
508
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
509
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
510
+            }
511
+
512
+            return ""
513
+        }
514
+
515
+        data = try dataPreprocessor.preprocess(data)
516
+
517
+        var convertedEncoding = encoding
518
+
519
+        if let encodingName = response?.textEncodingName as CFString?, convertedEncoding == nil {
520
+            let ianaCharSet = CFStringConvertIANACharSetNameToEncoding(encodingName)
521
+            let nsStringEncoding = CFStringConvertEncodingToNSStringEncoding(ianaCharSet)
522
+            convertedEncoding = String.Encoding(rawValue: nsStringEncoding)
523
+        }
524
+
525
+        let actualEncoding = convertedEncoding ?? .isoLatin1
526
+
527
+        guard let string = String(data: data, encoding: actualEncoding) else {
528
+            throw AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding))
529
+        }
530
+
531
+        return string
532
+    }
533
+}
534
+
535
+extension DataRequest {
536
+    /// Adds a handler to be called once the request has finished.
537
+    ///
538
+    /// - Parameters:
539
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
540
+    ///   - encoding:          The string encoding. Defaults to `nil`, in which case the encoding will be determined from
541
+    ///                        the server response, falling back to the default HTTP character set, `ISO-8859-1`.
542
+    ///   - completionHandler: A closure to be executed once the request has finished.
543
+    ///
544
+    /// - Returns:             The request.
545
+    @discardableResult
546
+    public func responseString(queue: DispatchQueue = .main,
547
+                               encoding: String.Encoding? = nil,
548
+                               completionHandler: @escaping (AFDataResponse<String>) -> Void) -> Self {
549
+        return response(queue: queue,
550
+                        responseSerializer: StringResponseSerializer(encoding: encoding),
551
+                        completionHandler: completionHandler)
552
+    }
553
+}
554
+
555
+extension DownloadRequest {
556
+    /// Adds a handler to be called once the request has finished.
557
+    ///
558
+    /// - Parameters:
559
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
560
+    ///   - encoding:          The string encoding. Defaults to `nil`, in which case the encoding will be determined from
561
+    ///                        the server response, falling back to the default HTTP character set, `ISO-8859-1`.
562
+    ///   - completionHandler: A closure to be executed once the request has finished.
563
+    ///
564
+    /// - Returns:             The request.
565
+    @discardableResult
566
+    public func responseString(queue: DispatchQueue = .main,
567
+                               encoding: String.Encoding? = nil,
568
+                               completionHandler: @escaping (AFDownloadResponse<String>) -> Void)
569
+        -> Self {
570
+        return response(queue: queue,
571
+                        responseSerializer: StringResponseSerializer(encoding: encoding),
572
+                        completionHandler: completionHandler)
573
+    }
574
+}
575
+
576
+// MARK: - JSON
577
+
578
+/// A `ResponseSerializer` that decodes the response data using `JSONSerialization`. By default, a request returning
579
+/// `nil` or no data is considered an error. However, if the response is has a status code valid for empty responses
580
+/// (`204`, `205`), then an `NSNull`  value is returned.
581
+public final class JSONResponseSerializer: ResponseSerializer {
582
+    public let dataPreprocessor: DataPreprocessor
583
+    public let emptyResponseCodes: Set<Int>
584
+    public let emptyRequestMethods: Set<HTTPMethod>
585
+    /// `JSONSerialization.ReadingOptions` used when serializing a response.
586
+    public let options: JSONSerialization.ReadingOptions
587
+
588
+    /// Creates an instance with the provided values.
589
+    ///
590
+    /// - Parameters:
591
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
592
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
593
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
594
+    ///   - options:             The options to use. `.allowFragments` by default.
595
+    public init(dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
596
+                emptyResponseCodes: Set<Int> = JSONResponseSerializer.defaultEmptyResponseCodes,
597
+                emptyRequestMethods: Set<HTTPMethod> = JSONResponseSerializer.defaultEmptyRequestMethods,
598
+                options: JSONSerialization.ReadingOptions = .allowFragments) {
599
+        self.dataPreprocessor = dataPreprocessor
600
+        self.emptyResponseCodes = emptyResponseCodes
601
+        self.emptyRequestMethods = emptyRequestMethods
602
+        self.options = options
603
+    }
604
+
605
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Any {
606
+        guard error == nil else { throw error! }
607
+
608
+        guard var data = data, !data.isEmpty else {
609
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
610
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
611
+            }
612
+
613
+            return NSNull()
614
+        }
615
+
616
+        data = try dataPreprocessor.preprocess(data)
617
+
618
+        do {
619
+            return try JSONSerialization.jsonObject(with: data, options: options)
620
+        } catch {
621
+            throw AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error))
622
+        }
623
+    }
624
+}
625
+
626
+extension DataRequest {
627
+    /// Adds a handler to be called once the request has finished.
628
+    ///
629
+    /// - Parameters:
630
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
631
+    ///   - options:           The JSON serialization reading options. `.allowFragments` by default.
632
+    ///   - completionHandler: A closure to be executed once the request has finished.
633
+    ///
634
+    /// - Returns:             The request.
635
+    @discardableResult
636
+    public func responseJSON(queue: DispatchQueue = .main,
637
+                             options: JSONSerialization.ReadingOptions = .allowFragments,
638
+                             completionHandler: @escaping (AFDataResponse<Any>) -> Void) -> Self {
639
+        return response(queue: queue,
640
+                        responseSerializer: JSONResponseSerializer(options: options),
641
+                        completionHandler: completionHandler)
642
+    }
643
+}
644
+
645
+extension DownloadRequest {
646
+    /// Adds a handler to be called once the request has finished.
647
+    ///
648
+    /// - Parameters:
649
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
650
+    ///   - options:           The JSON serialization reading options. `.allowFragments` by default.
651
+    ///   - completionHandler: A closure to be executed once the request has finished.
652
+    ///
653
+    /// - Returns:             The request.
654
+    @discardableResult
655
+    public func responseJSON(queue: DispatchQueue = .main,
656
+                             options: JSONSerialization.ReadingOptions = .allowFragments,
657
+                             completionHandler: @escaping (AFDownloadResponse<Any>) -> Void)
658
+        -> Self {
659
+        return response(queue: queue,
660
+                        responseSerializer: JSONResponseSerializer(options: options),
661
+                        completionHandler: completionHandler)
662
+    }
663
+}
664
+
665
+// MARK: - Empty
666
+
667
+/// Protocol representing an empty response. Use `T.emptyValue()` to get an instance.
668
+public protocol EmptyResponse {
669
+    /// Empty value for the conforming type.
670
+    ///
671
+    /// - Returns: Value of `Self` to use for empty values.
672
+    static func emptyValue() -> Self
673
+}
674
+
675
+/// Type representing an empty response. Use `Empty.value` to get the static instance.
676
+public struct Empty: Decodable {
677
+    /// Static `Empty` instance used for all `Empty` responses.
678
+    public static let value = Empty()
679
+}
680
+
681
+extension Empty: EmptyResponse {
682
+    public static func emptyValue() -> Empty {
683
+        return value
684
+    }
685
+}
686
+
687
+// MARK: - DataDecoder Protocol
688
+
689
+/// Any type which can decode `Data` into a `Decodable` type.
690
+public protocol DataDecoder {
691
+    /// Decode `Data` into the provided type.
692
+    ///
693
+    /// - Parameters:
694
+    ///   - type:  The `Type` to be decoded.
695
+    ///   - data:  The `Data` to be decoded.
696
+    ///
697
+    /// - Returns: The decoded value of type `D`.
698
+    /// - Throws:  Any error that occurs during decode.
699
+    func decode<D: Decodable>(_ type: D.Type, from data: Data) throws -> D
700
+}
701
+
702
+/// `JSONDecoder` automatically conforms to `DataDecoder`.
703
+extension JSONDecoder: DataDecoder {}
704
+
705
+// MARK: - Decodable
706
+
707
+/// A `ResponseSerializer` that decodes the response data as a generic value using any type that conforms to
708
+/// `DataDecoder`. By default, this is an instance of `JSONDecoder`. Additionally, a request returning `nil` or no data
709
+/// is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`), then
710
+/// the `Empty.value` value is returned.
711
+public final class DecodableResponseSerializer<T: Decodable>: ResponseSerializer {
712
+    public let dataPreprocessor: DataPreprocessor
713
+    /// The `DataDecoder` instance used to decode responses.
714
+    public let decoder: DataDecoder
715
+    public let emptyResponseCodes: Set<Int>
716
+    public let emptyRequestMethods: Set<HTTPMethod>
717
+
718
+    /// Creates an instance using the values provided.
719
+    ///
720
+    /// - Parameters:
721
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
722
+    ///   - decoder:             The `DataDecoder`. `JSONDecoder()` by default.
723
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
724
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
725
+    public init(dataPreprocessor: DataPreprocessor = DecodableResponseSerializer.defaultDataPreprocessor,
726
+                decoder: DataDecoder = JSONDecoder(),
727
+                emptyResponseCodes: Set<Int> = DecodableResponseSerializer.defaultEmptyResponseCodes,
728
+                emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer.defaultEmptyRequestMethods) {
729
+        self.dataPreprocessor = dataPreprocessor
730
+        self.decoder = decoder
731
+        self.emptyResponseCodes = emptyResponseCodes
732
+        self.emptyRequestMethods = emptyRequestMethods
733
+    }
734
+
735
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> T {
736
+        guard error == nil else { throw error! }
737
+
738
+        guard var data = data, !data.isEmpty else {
739
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
740
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
741
+            }
742
+
743
+            guard let emptyResponseType = T.self as? EmptyResponse.Type, let emptyValue = emptyResponseType.emptyValue() as? T else {
744
+                throw AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "\(T.self)"))
745
+            }
746
+
747
+            return emptyValue
748
+        }
749
+
750
+        data = try dataPreprocessor.preprocess(data)
751
+
752
+        do {
753
+            return try decoder.decode(T.self, from: data)
754
+        } catch {
755
+            throw AFError.responseSerializationFailed(reason: .decodingFailed(error: error))
756
+        }
757
+    }
758
+}
759
+
760
+extension DataRequest {
761
+    /// Adds a handler to be called once the request has finished.
762
+    ///
763
+    /// - Parameters:
764
+    ///   - type:              `Decodable` type to decode from response data.
765
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
766
+    ///   - decoder:           `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
767
+    ///   - completionHandler: A closure to be executed once the request has finished.
768
+    ///
769
+    /// - Returns:             The request.
770
+    @discardableResult
771
+    public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
772
+                                                queue: DispatchQueue = .main,
773
+                                                decoder: DataDecoder = JSONDecoder(),
774
+                                                completionHandler: @escaping (AFDataResponse<T>) -> Void) -> Self {
775
+        return response(queue: queue,
776
+                        responseSerializer: DecodableResponseSerializer(decoder: decoder),
777
+                        completionHandler: completionHandler)
778
+    }
779
+}

+ 109
- 0
Pods/Alamofire/Source/Result+Alamofire.swift View File

@@ -0,0 +1,109 @@
1
+//
2
+//  Result+Alamofire.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
+/// Default type of `Result` returned by Alamofire, with an `AFError` `Failure` type.
28
+public typealias AFResult<Success> = Result<Success, AFError>
29
+
30
+// MARK: - Internal APIs
31
+
32
+extension Result {
33
+    /// Returns the associated value if the result is a success, `nil` otherwise.
34
+    var success: Success? {
35
+        guard case let .success(value) = self else { return nil }
36
+        return value
37
+    }
38
+
39
+    /// Returns the associated error value if the result is a failure, `nil` otherwise.
40
+    var failure: Failure? {
41
+        guard case let .failure(error) = self else { return nil }
42
+        return error
43
+    }
44
+
45
+    /// Initializes a `Result` from value or error. Returns `.failure` if the error is non-nil, `.success` otherwise.
46
+    ///
47
+    /// - Parameters:
48
+    ///   - value: A value.
49
+    ///   - error: An `Error`.
50
+    init(value: Success, error: Failure?) {
51
+        if let error = error {
52
+            self = .failure(error)
53
+        } else {
54
+            self = .success(value)
55
+        }
56
+    }
57
+
58
+    /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
59
+    ///
60
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
61
+    ///
62
+    ///     let possibleData: Result<Data, Error> = .success(Data(...))
63
+    ///     let possibleObject = possibleData.tryMap {
64
+    ///         try JSONSerialization.jsonObject(with: $0)
65
+    ///     }
66
+    ///
67
+    /// - parameter transform: A closure that takes the success value of the instance.
68
+    ///
69
+    /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
70
+    ///            same failure.
71
+    func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, Error> {
72
+        switch self {
73
+        case let .success(value):
74
+            do {
75
+                return try .success(transform(value))
76
+            } catch {
77
+                return .failure(error)
78
+            }
79
+        case let .failure(error):
80
+            return .failure(error)
81
+        }
82
+    }
83
+
84
+    /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
85
+    ///
86
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
87
+    ///
88
+    ///     let possibleData: Result<Data, Error> = .success(Data(...))
89
+    ///     let possibleObject = possibleData.tryMapError {
90
+    ///         try someFailableFunction(taking: $0)
91
+    ///     }
92
+    ///
93
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
94
+    ///
95
+    /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
96
+    ///            the same success.
97
+    func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> Result<Success, Error> {
98
+        switch self {
99
+        case let .failure(error):
100
+            do {
101
+                return try .failure(transform(error))
102
+            } catch {
103
+                return .failure(error)
104
+            }
105
+        case let .success(value):
106
+            return .success(value)
107
+        }
108
+    }
109
+}

+ 363
- 0
Pods/Alamofire/Source/RetryPolicy.swift View File

@@ -0,0 +1,363 @@
1
+//
2
+//  RetryPolicy.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 retry policy that retries requests using an exponential backoff for allowed HTTP methods and HTTP status codes
28
+/// as well as certain types of networking errors.
29
+open class RetryPolicy: RequestInterceptor {
30
+    /// The default retry limit for retry policies.
31
+    public static let defaultRetryLimit: UInt = 2
32
+
33
+    /// The default exponential backoff base for retry policies (must be a minimum of 2).
34
+    public static let defaultExponentialBackoffBase: UInt = 2
35
+
36
+    /// The default exponential backoff scale for retry policies.
37
+    public static let defaultExponentialBackoffScale: Double = 0.5
38
+
39
+    /// The default HTTP methods to retry.
40
+    /// See [RFC 2616 - Section 9.1.2](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) for more information.
41
+    public static let defaultRetryableHTTPMethods: Set<HTTPMethod> = [.delete, // [Delete](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7) - not always idempotent
42
+                                                                      .get, // [GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3) - generally idempotent
43
+                                                                      .head, // [HEAD](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4) - generally idempotent
44
+                                                                      .options, // [OPTIONS](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2) - inherently idempotent
45
+                                                                      .put, // [PUT](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6) - not always idempotent
46
+                                                                      .trace // [TRACE](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.8) - inherently idempotent
47
+    ]
48
+
49
+    /// The default HTTP status codes to retry.
50
+    /// See [RFC 2616 - Section 10](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10) for more information.
51
+    public static let defaultRetryableHTTPStatusCodes: Set<Int> = [408, // [Request Timeout](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9)
52
+                                                                   500, // [Internal Server Error](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1)
53
+                                                                   502, // [Bad Gateway](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3)
54
+                                                                   503, // [Service Unavailable](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4)
55
+                                                                   504 // [Gateway Timeout](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.5)
56
+    ]
57
+
58
+    /// The default URL error codes to retry.
59
+    public static let defaultRetryableURLErrorCodes: Set<URLError.Code> = [// [Security] App Transport Security disallowed a connection because there is no secure network connection.
60
+        //   - [Disabled] ATS settings do not change at runtime.
61
+        // .appTransportSecurityRequiresSecureConnection,
62
+
63
+        // [System] An app or app extension attempted to connect to a background session that is already connected to a
64
+        // process.
65
+        //   - [Enabled] The other process could release the background session.
66
+        .backgroundSessionInUseByAnotherProcess,
67
+                                                                           
68
+        // [System] The shared container identifier of the URL session configuration is needed but has not been set.
69
+        //   - [Disabled] Cannot change at runtime.
70
+        // .backgroundSessionRequiresSharedContainer,
71
+
72
+        // [System] The app is suspended or exits while a background data task is processing.
73
+        //   - [Enabled] App can be foregrounded or launched to recover.
74
+        .backgroundSessionWasDisconnected,
75
+                                                                           
76
+        // [Network] The URL Loading system received bad data from the server.
77
+        //   - [Enabled] Server could return valid data when retrying.
78
+        .badServerResponse,
79
+                                                                           
80
+        // [Resource] A malformed URL prevented a URL request from being initiated.
81
+        //   - [Disabled] URL was most likely constructed incorrectly.
82
+        // .badURL,
83
+
84
+        // [System] A connection was attempted while a phone call is active on a network that does not support
85
+        // simultaneous phone and data communication (EDGE or GPRS).
86
+        //   - [Enabled] Phone call could be ended to allow request to recover.
87
+        .callIsActive,
88
+                                                                           
89
+        // [Client] An asynchronous load has been canceled.
90
+        //   - [Disabled] Request was cancelled by the client.
91
+        // .cancelled,
92
+
93
+        // [File System] A download task couldn’t close the downloaded file on disk.
94
+        //   - [Disabled] File system error is unlikely to recover with retry.
95
+        // .cannotCloseFile,
96
+
97
+        // [Network] An attempt to connect to a host failed.
98
+        //   - [Enabled] Server or DNS lookup could recover during retry.
99
+        .cannotConnectToHost,
100
+                                                                           
101
+        // [File System] A download task couldn’t create the downloaded file on disk because of an I/O failure.
102
+        //   - [Disabled] File system error is unlikely to recover with retry.
103
+        // .cannotCreateFile,
104
+
105
+        // [Data] Content data received during a connection request had an unknown content encoding.
106
+        //   - [Disabled] Server is unlikely to modify the content encoding during a retry.
107
+        // .cannotDecodeContentData,
108
+
109
+        // [Data] Content data received during a connection request could not be decoded for a known content encoding.
110
+        //   - [Disabled] Server is unlikely to modify the content encoding during a retry.
111
+        // .cannotDecodeRawData,
112
+
113
+        // [Network] The host name for a URL could not be resolved.
114
+        //   - [Enabled] Server or DNS lookup could recover during retry.
115
+        .cannotFindHost,
116
+                                                                           
117
+        // [Network] A request to load an item only from the cache could not be satisfied.
118
+        //   - [Enabled] Cache could be populated during a retry.
119
+        .cannotLoadFromNetwork,
120
+                                                                           
121
+        // [File System] A download task was unable to move a downloaded file on disk.
122
+        //   - [Disabled] File system error is unlikely to recover with retry.
123
+        // .cannotMoveFile,
124
+
125
+        // [File System] A download task was unable to open the downloaded file on disk.
126
+        //   - [Disabled] File system error is unlikely to recover with retry.
127
+        // .cannotOpenFile,
128
+
129
+        // [Data] A task could not parse a response.
130
+        //   - [Disabled] Invalid response is unlikely to recover with retry.
131
+        // .cannotParseResponse,
132
+
133
+        // [File System] A download task was unable to remove a downloaded file from disk.
134
+        //   - [Disabled] File system error is unlikely to recover with retry.
135
+        // .cannotRemoveFile,
136
+
137
+        // [File System] A download task was unable to write to the downloaded file on disk.
138
+        //   - [Disabled] File system error is unlikely to recover with retry.
139
+        // .cannotWriteToFile,
140
+
141
+        // [Security] A client certificate was rejected.
142
+        //   - [Disabled] Client certificate is unlikely to change with retry.
143
+        // .clientCertificateRejected,
144
+
145
+        // [Security] A client certificate was required to authenticate an SSL connection during a request.
146
+        //   - [Disabled] Client certificate is unlikely to be provided with retry.
147
+        // .clientCertificateRequired,
148
+
149
+        // [Data] The length of the resource data exceeds the maximum allowed.
150
+        //   - [Disabled] Resource will likely still exceed the length maximum on retry.
151
+        // .dataLengthExceedsMaximum,
152
+
153
+        // [System] The cellular network disallowed a connection.
154
+        //   - [Enabled] WiFi connection could be established during retry.
155
+        .dataNotAllowed,
156
+                                                                           
157
+        // [Network] The host address could not be found via DNS lookup.
158
+        //   - [Enabled] DNS lookup could succeed during retry.
159
+        .dnsLookupFailed,
160
+                                                                           
161
+        // [Data] A download task failed to decode an encoded file during the download.
162
+        //   - [Enabled] Server could correct the decoding issue with retry.
163
+        .downloadDecodingFailedMidStream,
164
+                                                                           
165
+        // [Data] A download task failed to decode an encoded file after downloading.
166
+        //   - [Enabled] Server could correct the decoding issue with retry.
167
+        .downloadDecodingFailedToComplete,
168
+                                                                           
169
+        // [File System] A file does not exist.
170
+        //   - [Disabled] File system error is unlikely to recover with retry.
171
+        // .fileDoesNotExist,
172
+
173
+        // [File System] A request for an FTP file resulted in the server responding that the file is not a plain file,
174
+        // but a directory.
175
+        //   - [Disabled] FTP directory is not likely to change to a file during a retry.
176
+        // .fileIsDirectory,
177
+
178
+        // [Network] A redirect loop has been detected or the threshold for number of allowable redirects has been
179
+        // exceeded (currently 16).
180
+        //   - [Disabled] The redirect loop is unlikely to be resolved within the retry window.
181
+        // .httpTooManyRedirects,
182
+
183
+        // [System] The attempted connection required activating a data context while roaming, but international roaming
184
+        // is disabled.
185
+        //   - [Enabled] WiFi connection could be established during retry.
186
+        .internationalRoamingOff,
187
+                                                                           
188
+        // [Connectivity] A client or server connection was severed in the middle of an in-progress load.
189
+        //   - [Enabled] A network connection could be established during retry.
190
+        .networkConnectionLost,
191
+                                                                           
192
+        // [File System] A resource couldn’t be read because of insufficient permissions.
193
+        //   - [Disabled] Permissions are unlikely to be granted during retry.
194
+        // .noPermissionsToReadFile,
195
+
196
+        // [Connectivity] A network resource was requested, but an internet connection has not been established and
197
+        // cannot be established automatically.
198
+        //   - [Enabled] A network connection could be established during retry.
199
+        .notConnectedToInternet,
200
+                                                                           
201
+        // [Resource] A redirect was specified by way of server response code, but the server did not accompany this
202
+        // code with a redirect URL.
203
+        //   - [Disabled] The redirect URL is unlikely to be supplied during a retry.
204
+        // .redirectToNonExistentLocation,
205
+
206
+        // [Client] A body stream is needed but the client did not provide one.
207
+        //   - [Disabled] The client will be unlikely to supply a body stream during retry.
208
+        // .requestBodyStreamExhausted,
209
+
210
+        // [Resource] A requested resource couldn’t be retrieved.
211
+        //   - [Disabled] The resource is unlikely to become available during the retry window.
212
+        // .resourceUnavailable,
213
+
214
+        // [Security] An attempt to establish a secure connection failed for reasons that can’t be expressed more
215
+        // specifically.
216
+        //   - [Enabled] The secure connection could be established during a retry given the lack of specificity
217
+        //     provided by the error.
218
+        .secureConnectionFailed,
219
+                                                                           
220
+        // [Security] A server certificate had a date which indicates it has expired, or is not yet valid.
221
+        //   - [Enabled] The server certificate could become valid within the retry window.
222
+        .serverCertificateHasBadDate,
223
+                                                                           
224
+        // [Security] A server certificate was not signed by any root server.
225
+        //   - [Disabled] The server certificate is unlikely to change during the retry window.
226
+        // .serverCertificateHasUnknownRoot,
227
+
228
+        // [Security] A server certificate is not yet valid.
229
+        //   - [Enabled] The server certificate could become valid within the retry window.
230
+        .serverCertificateNotYetValid,
231
+                                                                           
232
+        // [Security] A server certificate was signed by a root server that isn’t trusted.
233
+        //   - [Disabled] The server certificate is unlikely to become trusted within the retry window.
234
+        // .serverCertificateUntrusted,
235
+
236
+        // [Network] An asynchronous operation timed out.
237
+        //   - [Enabled] The request timed out for an unknown reason and should be retried.
238
+        .timedOut
239
+
240
+        // [System] The URL Loading System encountered an error that it can’t interpret.
241
+        //   - [Disabled] The error could not be interpreted and is unlikely to be recovered from during a retry.
242
+        // .unknown,
243
+
244
+        // [Resource] A properly formed URL couldn’t be handled by the framework.
245
+        //   - [Disabled] The URL is unlikely to change during a retry.
246
+        // .unsupportedURL,
247
+
248
+        // [Client] Authentication is required to access a resource.
249
+        //   - [Disabled] The user authentication is unlikely to be provided by retrying.
250
+        // .userAuthenticationRequired,
251
+
252
+        // [Client] An asynchronous request for authentication has been canceled by the user.
253
+        //   - [Disabled] The user cancelled authentication and explicitly took action to not retry.
254
+        // .userCancelledAuthentication,
255
+
256
+        // [Resource] A server reported that a URL has a non-zero content length, but terminated the network connection
257
+        // gracefully without sending any data.
258
+        //   - [Disabled] The server is unlikely to provide data during the retry window.
259
+        // .zeroByteResource,
260
+    ]
261
+
262
+    /// The total number of times the request is allowed to be retried.
263
+    public let retryLimit: UInt
264
+
265
+    /// The base of the exponential backoff policy (should always be greater than or equal to 2).
266
+    public let exponentialBackoffBase: UInt
267
+
268
+    /// The scale of the exponential backoff.
269
+    public let exponentialBackoffScale: Double
270
+
271
+    /// The HTTP methods that are allowed to be retried.
272
+    public let retryableHTTPMethods: Set<HTTPMethod>
273
+
274
+    /// The HTTP status codes that are automatically retried by the policy.
275
+    public let retryableHTTPStatusCodes: Set<Int>
276
+
277
+    /// The URL error codes that are automatically retried by the policy.
278
+    public let retryableURLErrorCodes: Set<URLError.Code>
279
+
280
+    /// Creates an `ExponentialBackoffRetryPolicy` from the specified parameters.
281
+    ///
282
+    /// - Parameters:
283
+    ///   - retryLimit:               The total number of times the request is allowed to be retried. `2` by default.
284
+    ///   - exponentialBackoffBase:   The base of the exponential backoff policy. `2` by default.
285
+    ///   - exponentialBackoffScale:  The scale of the exponential backoff. `0.5` by default.
286
+    ///   - retryableHTTPMethods:     The HTTP methods that are allowed to be retried.
287
+    ///                               `RetryPolicy.defaultRetryableHTTPMethods` by default.
288
+    ///   - retryableHTTPStatusCodes: The HTTP status codes that are automatically retried by the policy.
289
+    ///                               `RetryPolicy.defaultRetryableHTTPStatusCodes` by default.
290
+    ///   - retryableURLErrorCodes:   The URL error codes that are automatically retried by the policy.
291
+    ///                               `RetryPolicy.defaultRetryableURLErrorCodes` by default.
292
+    public init(retryLimit: UInt = RetryPolicy.defaultRetryLimit,
293
+                exponentialBackoffBase: UInt = RetryPolicy.defaultExponentialBackoffBase,
294
+                exponentialBackoffScale: Double = RetryPolicy.defaultExponentialBackoffScale,
295
+                retryableHTTPMethods: Set<HTTPMethod> = RetryPolicy.defaultRetryableHTTPMethods,
296
+                retryableHTTPStatusCodes: Set<Int> = RetryPolicy.defaultRetryableHTTPStatusCodes,
297
+                retryableURLErrorCodes: Set<URLError.Code> = RetryPolicy.defaultRetryableURLErrorCodes) {
298
+        precondition(exponentialBackoffBase >= 2, "The `exponentialBackoffBase` must be a minimum of 2.")
299
+
300
+        self.retryLimit = retryLimit
301
+        self.exponentialBackoffBase = exponentialBackoffBase
302
+        self.exponentialBackoffScale = exponentialBackoffScale
303
+        self.retryableHTTPMethods = retryableHTTPMethods
304
+        self.retryableHTTPStatusCodes = retryableHTTPStatusCodes
305
+        self.retryableURLErrorCodes = retryableURLErrorCodes
306
+    }
307
+
308
+    open func retry(_ request: Request,
309
+                    for session: Session,
310
+                    dueTo error: Error,
311
+                    completion: @escaping (RetryResult) -> Void) {
312
+        if
313
+            request.retryCount < retryLimit,
314
+            let httpMethod = request.request?.method,
315
+            retryableHTTPMethods.contains(httpMethod),
316
+            shouldRetry(response: request.response, error: error) {
317
+            let timeDelay = pow(Double(exponentialBackoffBase), Double(request.retryCount)) * exponentialBackoffScale
318
+            completion(.retryWithDelay(timeDelay))
319
+        } else {
320
+            completion(.doNotRetry)
321
+        }
322
+    }
323
+
324
+    private func shouldRetry(response: HTTPURLResponse?, error: Error) -> Bool {
325
+        if let statusCode = response?.statusCode, retryableHTTPStatusCodes.contains(statusCode) {
326
+            return true
327
+        } else if let errorCode = (error as? URLError)?.code, retryableURLErrorCodes.contains(errorCode) {
328
+            return true
329
+        }
330
+
331
+        return false
332
+    }
333
+}
334
+
335
+// MARK: -
336
+
337
+/// A retry policy that automatically retries idempotent requests for network connection lost errors. For more
338
+/// information about retrying network connection lost errors, please refer to Apple's
339
+/// [technical document](https://developer.apple.com/library/content/qa/qa1941/_index.html).
340
+open class ConnectionLostRetryPolicy: RetryPolicy {
341
+    /// Creates a `ConnectionLostRetryPolicy` instance from the specified parameters.
342
+    ///
343
+    /// - Parameters:
344
+    ///   - retryLimit:              The total number of times the request is allowed to be retried.
345
+    ///                              `RetryPolicy.defaultRetryLimit` by default.
346
+    ///   - exponentialBackoffBase:  The base of the exponential backoff policy.
347
+    ///                              `RetryPolicy.defaultExponentialBackoffBase` by default.
348
+    ///   - exponentialBackoffScale: The scale of the exponential backoff.
349
+    ///                              `RetryPolicy.defaultExponentialBackoffScale` by default.
350
+    ///   - retryableHTTPMethods:    The idempotent http methods to retry.
351
+    ///                              `RetryPolicy.defaultRetryableHTTPMethods` by default.
352
+    public init(retryLimit: UInt = RetryPolicy.defaultRetryLimit,
353
+                exponentialBackoffBase: UInt = RetryPolicy.defaultExponentialBackoffBase,
354
+                exponentialBackoffScale: Double = RetryPolicy.defaultExponentialBackoffScale,
355
+                retryableHTTPMethods: Set<HTTPMethod> = RetryPolicy.defaultRetryableHTTPMethods) {
356
+        super.init(retryLimit: retryLimit,
357
+                   exponentialBackoffBase: exponentialBackoffBase,
358
+                   exponentialBackoffScale: exponentialBackoffScale,
359
+                   retryableHTTPMethods: retryableHTTPMethods,
360
+                   retryableHTTPStatusCodes: [],
361
+                   retryableURLErrorCodes: [.networkConnectionLost])
362
+    }
363
+}

+ 606
- 0
Pods/Alamofire/Source/ServerTrustEvaluation.swift View File

@@ -0,0 +1,606 @@
1
+//
2
+//  ServerTrustPolicy.swift
3
+//
4
+//  Copyright (c) 2014-2016 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
+/// Responsible for managing the mapping of `ServerTrustEvaluating` values to given hosts.
28
+open class ServerTrustManager {
29
+    /// Determines whether all hosts for this `ServerTrustManager` must be evaluated. `true` by default.
30
+    public let allHostsMustBeEvaluated: Bool
31
+
32
+    /// The dictionary of policies mapped to a particular host.
33
+    public let evaluators: [String: ServerTrustEvaluating]
34
+
35
+    /// Initializes the `ServerTrustManager` instance with the given evaluators.
36
+    ///
37
+    /// Since different servers and web services can have different leaf certificates, intermediate and even root
38
+    /// certificates, it is important to have the flexibility to specify evaluation policies on a per host basis. This
39
+    /// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key
40
+    /// pinning for host3 and disabling evaluation for host4.
41
+    ///
42
+    /// - Parameters:
43
+    ///   - allHostsMustBeEvaluated: The value determining whether all hosts for this instance must be evaluated. `true`
44
+    ///                              by default.
45
+    ///   - evaluators:              A dictionary of evaluators mapped to hosts.
46
+    public init(allHostsMustBeEvaluated: Bool = true, evaluators: [String: ServerTrustEvaluating]) {
47
+        self.allHostsMustBeEvaluated = allHostsMustBeEvaluated
48
+        self.evaluators = evaluators
49
+    }
50
+
51
+    /// Returns the `ServerTrustEvaluating` value for the given host, if one is set.
52
+    ///
53
+    /// By default, this method will return the policy that perfectly matches the given host. Subclasses could override
54
+    /// this method and implement more complex mapping implementations such as wildcards.
55
+    ///
56
+    /// - Parameter host: The host to use when searching for a matching policy.
57
+    ///
58
+    /// - Returns:        The `ServerTrustEvaluating` value for the given host if found, `nil` otherwise.
59
+    /// - Throws:         `AFError.serverTrustEvaluationFailed` if `allHostsMustBeEvaluated` is `true` and no matching
60
+    ///                   evaluators are found.
61
+    open func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {
62
+        guard let evaluator = evaluators[host] else {
63
+            if allHostsMustBeEvaluated {
64
+                throw AFError.serverTrustEvaluationFailed(reason: .noRequiredEvaluator(host: host))
65
+            }
66
+
67
+            return nil
68
+        }
69
+
70
+        return evaluator
71
+    }
72
+}
73
+
74
+/// A protocol describing the API used to evaluate server trusts.
75
+public protocol ServerTrustEvaluating {
76
+#if os(Linux)
77
+// Implement this once Linux has API for evaluating server trusts.
78
+#else
79
+    /// Evaluates the given `SecTrust` value for the given `host`.
80
+    ///
81
+    /// - Parameters:
82
+    ///   - trust: The `SecTrust` value to evaluate.
83
+    ///   - host:  The host for which to evaluate the `SecTrust` value.
84
+    ///
85
+    /// - Returns: A `Bool` indicating whether the evaluator considers the `SecTrust` value valid for `host`.
86
+    func evaluate(_ trust: SecTrust, forHost host: String) throws
87
+#endif
88
+}
89
+
90
+// MARK: - Server Trust Evaluators
91
+
92
+/// An evaluator which uses the default server trust evaluation while allowing you to control whether to validate the
93
+/// host provided by the challenge. Applications are encouraged to always validate the host in production environments
94
+/// to guarantee the validity of the server's certificate chain.
95
+public final class DefaultTrustEvaluator: ServerTrustEvaluating {
96
+    private let validateHost: Bool
97
+
98
+    /// Creates a `DefaultTrustEvaluator`.
99
+    ///
100
+    /// - Parameter validateHost: Determines whether or not the evaluator should validate the host. `true` by default.
101
+    public init(validateHost: Bool = true) {
102
+        self.validateHost = validateHost
103
+    }
104
+
105
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
106
+        if validateHost {
107
+            try trust.af.performValidation(forHost: host)
108
+        }
109
+
110
+        try trust.af.performDefaultValidation(forHost: host)
111
+    }
112
+}
113
+
114
+/// An evaluator which Uses the default and revoked server trust evaluations allowing you to control whether to validate
115
+/// the host provided by the challenge as well as specify the revocation flags for testing for revoked certificates.
116
+/// Apple platforms did not start testing for revoked certificates automatically until iOS 10.1, macOS 10.12 and tvOS
117
+/// 10.1 which is demonstrated in our TLS tests. Applications are encouraged to always validate the host in production
118
+/// environments to guarantee the validity of the server's certificate chain.
119
+public final class RevocationTrustEvaluator: ServerTrustEvaluating {
120
+    /// Represents the options to be use when evaluating the status of a certificate.
121
+    /// Only Revocation Policy Constants are valid, and can be found in [Apple's documentation](https://developer.apple.com/documentation/security/certificate_key_and_trust_services/policies/1563600-revocation_policy_constants).
122
+    public struct Options: OptionSet {
123
+        /// Perform revocation checking using the CRL (Certification Revocation List) method.
124
+        public static let crl = Options(rawValue: kSecRevocationCRLMethod)
125
+        /// Consult only locally cached replies; do not use network access.
126
+        public static let networkAccessDisabled = Options(rawValue: kSecRevocationNetworkAccessDisabled)
127
+        /// Perform revocation checking using OCSP (Online Certificate Status Protocol).
128
+        public static let ocsp = Options(rawValue: kSecRevocationOCSPMethod)
129
+        /// Prefer CRL revocation checking over OCSP; by default, OCSP is preferred.
130
+        public static let preferCRL = Options(rawValue: kSecRevocationPreferCRL)
131
+        /// Require a positive response to pass the policy. If the flag is not set, revocation checking is done on a
132
+        /// "best attempt" basis, where failure to reach the server is not considered fatal.
133
+        public static let requirePositiveResponse = Options(rawValue: kSecRevocationRequirePositiveResponse)
134
+        /// Perform either OCSP or CRL checking. The checking is performed according to the method(s) specified in the
135
+        /// certificate and the value of `preferCRL`.
136
+        public static let any = Options(rawValue: kSecRevocationUseAnyAvailableMethod)
137
+
138
+        /// The raw value of the option.
139
+        public let rawValue: CFOptionFlags
140
+
141
+        /// Creates an `Options` value with the given `CFOptionFlags`.
142
+        ///
143
+        /// - Parameter rawValue: The `CFOptionFlags` value to initialize with.
144
+        public init(rawValue: CFOptionFlags) {
145
+            self.rawValue = rawValue
146
+        }
147
+    }
148
+
149
+    private let performDefaultValidation: Bool
150
+    private let validateHost: Bool
151
+    private let options: Options
152
+
153
+    /// Creates a `RevocationTrustEvaluator`.
154
+    ///
155
+    /// - Note: Default and host validation will fail when using this evaluator with self-signed certificates. Use
156
+    ///         `PinnedCertificatesTrustEvaluator` if you need to use self-signed certificates.
157
+    ///
158
+    /// - Parameters:
159
+    ///   - performDefaultValidation:     Determines whether default validation should be performed in addition to
160
+    ///                                   evaluating the pinned certificates. `true` by default.
161
+    ///   - validateHost:                 Determines whether or not the evaluator should validate the host, in addition
162
+    ///                                   to performing the default evaluation, even if `performDefaultValidation` is
163
+    ///                                   `false`. `true` by default.
164
+    ///   - options:                      The `Options` to use to check the revocation status of the certificate. `.any`
165
+    ///                                   by default.
166
+    public init(performDefaultValidation: Bool = true, validateHost: Bool = true, options: Options = .any) {
167
+        self.performDefaultValidation = performDefaultValidation
168
+        self.validateHost = validateHost
169
+        self.options = options
170
+    }
171
+
172
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
173
+        if performDefaultValidation {
174
+            try trust.af.performDefaultValidation(forHost: host)
175
+        }
176
+
177
+        if validateHost {
178
+            try trust.af.performValidation(forHost: host)
179
+        }
180
+
181
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
182
+            try trust.af.evaluate(afterApplying: SecPolicy.af.revocation(options: options))
183
+        } else {
184
+            try trust.af.validate(policy: SecPolicy.af.revocation(options: options)) { status, result in
185
+                AFError.serverTrustEvaluationFailed(reason: .revocationCheckFailed(output: .init(host, trust, status, result), options: options))
186
+            }
187
+        }
188
+    }
189
+}
190
+
191
+/// Uses the pinned certificates to validate the server trust. The server trust is considered valid if one of the pinned
192
+/// certificates match one of the server certificates. By validating both the certificate chain and host, certificate
193
+/// pinning provides a very secure form of server trust validation mitigating most, if not all, MITM attacks.
194
+/// Applications are encouraged to always validate the host and require a valid certificate chain in production
195
+/// environments.
196
+public final class PinnedCertificatesTrustEvaluator: ServerTrustEvaluating {
197
+    private let certificates: [SecCertificate]
198
+    private let acceptSelfSignedCertificates: Bool
199
+    private let performDefaultValidation: Bool
200
+    private let validateHost: Bool
201
+
202
+    /// Creates a `PinnedCertificatesTrustEvaluator`.
203
+    ///
204
+    /// - Parameters:
205
+    ///   - certificates:                 The certificates to use to evaluate the trust. All `cer`, `crt`, and `der`
206
+    ///                                   certificates in `Bundle.main` by default.
207
+    ///   - acceptSelfSignedCertificates: Adds the provided certificates as anchors for the trust evaluation, allowing
208
+    ///                                   self-signed certificates to pass. `false` by default. THIS SETTING SHOULD BE
209
+    ///                                   FALSE IN PRODUCTION!
210
+    ///   - performDefaultValidation:     Determines whether default validation should be performed in addition to
211
+    ///                                   evaluating the pinned certificates. `true` by default.
212
+    ///   - validateHost:                 Determines whether or not the evaluator should validate the host, in addition
213
+    ///                                   to performing the default evaluation, even if `performDefaultValidation` is
214
+    ///                                   `false`. `true` by default.
215
+    public init(certificates: [SecCertificate] = Bundle.main.af.certificates,
216
+                acceptSelfSignedCertificates: Bool = false,
217
+                performDefaultValidation: Bool = true,
218
+                validateHost: Bool = true) {
219
+        self.certificates = certificates
220
+        self.acceptSelfSignedCertificates = acceptSelfSignedCertificates
221
+        self.performDefaultValidation = performDefaultValidation
222
+        self.validateHost = validateHost
223
+    }
224
+
225
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
226
+        guard !certificates.isEmpty else {
227
+            throw AFError.serverTrustEvaluationFailed(reason: .noCertificatesFound)
228
+        }
229
+
230
+        if acceptSelfSignedCertificates {
231
+            try trust.af.setAnchorCertificates(certificates)
232
+        }
233
+
234
+        if performDefaultValidation {
235
+            try trust.af.performDefaultValidation(forHost: host)
236
+        }
237
+
238
+        if validateHost {
239
+            try trust.af.performValidation(forHost: host)
240
+        }
241
+
242
+        let serverCertificatesData = Set(trust.af.certificateData)
243
+        let pinnedCertificatesData = Set(certificates.af.data)
244
+        let pinnedCertificatesInServerData = !serverCertificatesData.isDisjoint(with: pinnedCertificatesData)
245
+        if !pinnedCertificatesInServerData {
246
+            throw AFError.serverTrustEvaluationFailed(reason: .certificatePinningFailed(host: host,
247
+                                                                                        trust: trust,
248
+                                                                                        pinnedCertificates: certificates,
249
+                                                                                        serverCertificates: trust.af.certificates))
250
+        }
251
+    }
252
+}
253
+
254
+/// Uses the pinned public keys to validate the server trust. The server trust is considered valid if one of the pinned
255
+/// public keys match one of the server certificate public keys. By validating both the certificate chain and host,
256
+/// public key pinning provides a very secure form of server trust validation mitigating most, if not all, MITM attacks.
257
+/// Applications are encouraged to always validate the host and require a valid certificate chain in production
258
+/// environments.
259
+public final class PublicKeysTrustEvaluator: ServerTrustEvaluating {
260
+    private let keys: [SecKey]
261
+    private let performDefaultValidation: Bool
262
+    private let validateHost: Bool
263
+
264
+    /// Creates a `PublicKeysTrustEvaluator`.
265
+    ///
266
+    /// - Note: Default and host validation will fail when using this evaluator with self-signed certificates. Use
267
+    ///         `PinnedCertificatesTrustEvaluator` if you need to use self-signed certificates.
268
+    ///
269
+    /// - Parameters:
270
+    ///   - keys:                     The `SecKey`s to use to validate public keys. Defaults to the public keys of all
271
+    ///                               certificates included in the main bundle.
272
+    ///   - performDefaultValidation: Determines whether default validation should be performed in addition to
273
+    ///                               evaluating the pinned certificates. `true` by default.
274
+    ///   - validateHost:             Determines whether or not the evaluator should validate the host, in addition to
275
+    ///                               performing the default evaluation, even if `performDefaultValidation` is `false`.
276
+    ///                               `true` by default.
277
+    public init(keys: [SecKey] = Bundle.main.af.publicKeys,
278
+                performDefaultValidation: Bool = true,
279
+                validateHost: Bool = true) {
280
+        self.keys = keys
281
+        self.performDefaultValidation = performDefaultValidation
282
+        self.validateHost = validateHost
283
+    }
284
+
285
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
286
+        guard !keys.isEmpty else {
287
+            throw AFError.serverTrustEvaluationFailed(reason: .noPublicKeysFound)
288
+        }
289
+
290
+        if performDefaultValidation {
291
+            try trust.af.performDefaultValidation(forHost: host)
292
+        }
293
+
294
+        if validateHost {
295
+            try trust.af.performValidation(forHost: host)
296
+        }
297
+
298
+        let pinnedKeysInServerKeys: Bool = {
299
+            for serverPublicKey in trust.af.publicKeys {
300
+                for pinnedPublicKey in keys {
301
+                    if serverPublicKey == pinnedPublicKey {
302
+                        return true
303
+                    }
304
+                }
305
+            }
306
+            return false
307
+        }()
308
+
309
+        if !pinnedKeysInServerKeys {
310
+            throw AFError.serverTrustEvaluationFailed(reason: .publicKeyPinningFailed(host: host,
311
+                                                                                      trust: trust,
312
+                                                                                      pinnedKeys: keys,
313
+                                                                                      serverKeys: trust.af.publicKeys))
314
+        }
315
+    }
316
+}
317
+
318
+/// Uses the provided evaluators to validate the server trust. The trust is only considered valid if all of the
319
+/// evaluators consider it valid.
320
+public final class CompositeTrustEvaluator: ServerTrustEvaluating {
321
+    private let evaluators: [ServerTrustEvaluating]
322
+
323
+    /// Creates a `CompositeTrustEvaluator`.
324
+    ///
325
+    /// - Parameter evaluators: The `ServerTrustEvaluating` values used to evaluate the server trust.
326
+    public init(evaluators: [ServerTrustEvaluating]) {
327
+        self.evaluators = evaluators
328
+    }
329
+
330
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
331
+        try evaluators.evaluate(trust, forHost: host)
332
+    }
333
+}
334
+
335
+/// Disables all evaluation which in turn will always consider any server trust as valid.
336
+///
337
+/// **THIS EVALUATOR SHOULD NEVER BE USED IN PRODUCTION!**
338
+public final class DisabledEvaluator: ServerTrustEvaluating {
339
+    /// Creates an instance.
340
+    public init() {}
341
+
342
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {}
343
+}
344
+
345
+// MARK: - Extensions
346
+
347
+public extension Array where Element == ServerTrustEvaluating {
348
+#if os(Linux)
349
+// Add this same convenience method for Linux.
350
+#else
351
+    /// Evaluates the given `SecTrust` value for the given `host`.
352
+    ///
353
+    /// - Parameters:
354
+    ///   - trust: The `SecTrust` value to evaluate.
355
+    ///   - host:  The host for which to evaluate the `SecTrust` value.
356
+    ///
357
+    /// - Returns: Whether or not the evaluator considers the `SecTrust` value valid for `host`.
358
+    func evaluate(_ trust: SecTrust, forHost host: String) throws {
359
+        for evaluator in self {
360
+            try evaluator.evaluate(trust, forHost: host)
361
+        }
362
+    }
363
+#endif
364
+}
365
+
366
+extension Bundle: AlamofireExtended {}
367
+public extension AlamofireExtension where ExtendedType: Bundle {
368
+    /// Returns all valid `cer`, `crt`, and `der` certificates in the bundle.
369
+    var certificates: [SecCertificate] {
370
+        return paths(forResourcesOfTypes: [".cer", ".CER", ".crt", ".CRT", ".der", ".DER"]).compactMap { path in
371
+            guard
372
+                let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData,
373
+                let certificate = SecCertificateCreateWithData(nil, certificateData) else { return nil }
374
+
375
+            return certificate
376
+        }
377
+    }
378
+
379
+    /// Returns all public keys for the valid certificates in the bundle.
380
+    var publicKeys: [SecKey] {
381
+        return certificates.af.publicKeys
382
+    }
383
+
384
+    /// Returns all pathnames for the resources identified by the provided file extensions.
385
+    ///
386
+    /// - Parameter types: The filename extensions locate.
387
+    ///
388
+    /// - Returns:         All pathnames for the given filename extensions.
389
+    func paths(forResourcesOfTypes types: [String]) -> [String] {
390
+        return Array(Set(types.flatMap { type.paths(forResourcesOfType: $0, inDirectory: nil) }))
391
+    }
392
+}
393
+
394
+extension SecTrust: AlamofireExtended {}
395
+public extension AlamofireExtension where ExtendedType == SecTrust {
396
+    /// Evaluates `self` after applying the `SecPolicy` value provided.
397
+    ///
398
+    /// - Parameter policy: The `SecPolicy` to apply to `self` before evaluation.
399
+    ///
400
+    /// - Throws:           Any `Error` from applying the `SecPolicy` or from evaluation.
401
+    @available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *)
402
+    func evaluate(afterApplying policy: SecPolicy) throws {
403
+        try apply(policy: policy).af.evaluate()
404
+    }
405
+
406
+    /// Attempts to validate `self` using the `SecPolicy` provided and transforming any error produced using the closure passed.
407
+    ///
408
+    /// - Parameters:
409
+    ///   - policy:        The `SecPolicy` used to evaluate `self`.
410
+    ///   - errorProducer: The closure used transform the failed `OSStatus` and `SecTrustResultType`.
411
+    /// - Throws:          Any `Error` from applying the `policy`, or the result of `errorProducer` if validation fails.
412
+    @available(iOS, introduced: 10, deprecated: 12, renamed: "evaluate(afterApplying:)")
413
+    @available(macOS, introduced: 10.12, deprecated: 10.14, renamed: "evaluate(afterApplying:)")
414
+    @available(tvOS, introduced: 10, deprecated: 12, renamed: "evaluate(afterApplying:)")
415
+    @available(watchOS, introduced: 3, deprecated: 5, renamed: "evaluate(afterApplying:)")
416
+    func validate(policy: SecPolicy, errorProducer: (_ status: OSStatus, _ result: SecTrustResultType) -> Error) throws {
417
+        try apply(policy: policy).af.validate(errorProducer: errorProducer)
418
+    }
419
+
420
+    /// Applies a `SecPolicy` to `self`, throwing if it fails.
421
+    ///
422
+    /// - Parameter policy: The `SecPolicy`.
423
+    ///
424
+    /// - Returns: `self`, with the policy applied.
425
+    /// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.policyApplicationFailed` reason.
426
+    func apply(policy: SecPolicy) throws -> SecTrust {
427
+        let status = SecTrustSetPolicies(type, policy)
428
+
429
+        guard status.af.isSuccess else {
430
+            throw AFError.serverTrustEvaluationFailed(reason: .policyApplicationFailed(trust: type,
431
+                                                                                       policy: policy,
432
+                                                                                       status: status))
433
+        }
434
+
435
+        return type
436
+    }
437
+
438
+    /// Evaluate `self`, throwing an `Error` if evaluation fails.
439
+    ///
440
+    /// - Throws: `AFError.serverTrustEvaluationFailed` with reason `.trustValidationFailed` and associated error from
441
+    ///           the underlying evaluation.
442
+    @available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *)
443
+    func evaluate() throws {
444
+        var error: CFError?
445
+        let evaluationSucceeded = SecTrustEvaluateWithError(type, &error)
446
+
447
+        if !evaluationSucceeded {
448
+            throw AFError.serverTrustEvaluationFailed(reason: .trustEvaluationFailed(error: error))
449
+        }
450
+    }
451
+
452
+    /// Validate `self`, passing any failure values through `errorProducer`.
453
+    ///
454
+    /// - Parameter errorProducer: The closure used to transform the failed `OSStatus` and `SecTrustResultType` into an
455
+    ///                            `Error`.
456
+    /// - Throws:                  The `Error` produced by the `errorProducer` closure.
457
+    @available(iOS, introduced: 10, deprecated: 12, renamed: "evaluate()")
458
+    @available(macOS, introduced: 10.12, deprecated: 10.14, renamed: "evaluate()")
459
+    @available(tvOS, introduced: 10, deprecated: 12, renamed: "evaluate()")
460
+    @available(watchOS, introduced: 3, deprecated: 5, renamed: "evaluate()")
461
+    func validate(errorProducer: (_ status: OSStatus, _ result: SecTrustResultType) -> Error) throws {
462
+        var result = SecTrustResultType.invalid
463
+        let status = SecTrustEvaluate(type, &result)
464
+
465
+        guard status.af.isSuccess && result.af.isSuccess else {
466
+            throw errorProducer(status, result)
467
+        }
468
+    }
469
+
470
+    /// Sets a custom certificate chain on `self`, allowing full validation of a self-signed certificate and its chain.
471
+    ///
472
+    /// - Parameter certificates: The `SecCertificate`s to add to the chain.
473
+    /// - Throws:                 Any error produced when applying the new certificate chain.
474
+    func setAnchorCertificates(_ certificates: [SecCertificate]) throws {
475
+        // Add additional anchor certificates.
476
+        let status = SecTrustSetAnchorCertificates(type, certificates as CFArray)
477
+        guard status.af.isSuccess else {
478
+            throw AFError.serverTrustEvaluationFailed(reason: .settingAnchorCertificatesFailed(status: status,
479
+                                                                                               certificates: certificates))
480
+        }
481
+
482
+        // Reenable system anchor certificates.
483
+        let systemStatus = SecTrustSetAnchorCertificatesOnly(type, true)
484
+        guard systemStatus.af.isSuccess else {
485
+            throw AFError.serverTrustEvaluationFailed(reason: .settingAnchorCertificatesFailed(status: systemStatus,
486
+                                                                                               certificates: certificates))
487
+        }
488
+    }
489
+
490
+    /// The public keys contained in `self`.
491
+    var publicKeys: [SecKey] {
492
+        return certificates.af.publicKeys
493
+    }
494
+
495
+    /// The `SecCertificate`s contained i `self`.
496
+    var certificates: [SecCertificate] {
497
+        return (0..<SecTrustGetCertificateCount(type)).compactMap { index in
498
+            SecTrustGetCertificateAtIndex(type, index)
499
+        }
500
+    }
501
+
502
+    /// The `Data` values for all certificates contained in `self`.
503
+    var certificateData: [Data] {
504
+        return certificates.af.data
505
+    }
506
+
507
+    /// Validates `self` after applying `SecPolicy.af.default`. This evaluation does not validate the hostname.
508
+    ///
509
+    /// - Parameter host: The hostname, used only in the error output if validation fails.
510
+    /// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
511
+    func performDefaultValidation(forHost host: String) throws {
512
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
513
+            try evaluate(afterApplying: SecPolicy.af.default)
514
+        } else {
515
+            try validate(policy: SecPolicy.af.default) { status, result in
516
+                AFError.serverTrustEvaluationFailed(reason: .defaultEvaluationFailed(output: .init(host, type, status, result)))
517
+            }
518
+        }
519
+    }
520
+
521
+    /// Validates `self` after applying `SecPolicy.af.hostname(host)`, which performs the default validation as well as
522
+    /// hostname validation.
523
+    ///
524
+    /// - Parameter host: The hostname to use in the validation.
525
+    /// - Throws:         An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
526
+    func performValidation(forHost host: String) throws {
527
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
528
+            try evaluate(afterApplying: SecPolicy.af.hostname(host))
529
+        } else {
530
+            try validate(policy: SecPolicy.af.hostname(host)) { status, result in
531
+                AFError.serverTrustEvaluationFailed(reason: .hostValidationFailed(output: .init(host, type, status, result)))
532
+            }
533
+        }
534
+    }
535
+}
536
+
537
+extension SecPolicy: AlamofireExtended {}
538
+public extension AlamofireExtension where ExtendedType == SecPolicy {
539
+    /// Creates a `SecPolicy` instance which will validate server certificates but not require a host name match.
540
+    static let `default` = SecPolicyCreateSSL(true, nil)
541
+
542
+    /// Creates a `SecPolicy` instance which will validate server certificates and much match the provided hostname.
543
+    ///
544
+    /// - Parameter hostname: The hostname to validate against.
545
+    ///
546
+    /// - Returns:            The `SecPolicy`.
547
+    static func hostname(_ hostname: String) -> SecPolicy {
548
+        return SecPolicyCreateSSL(true, hostname as CFString)
549
+    }
550
+
551
+    /// Creates a `SecPolicy` which checks the revocation of certificates.
552
+    ///
553
+    /// - Parameter options: The `RevocationTrustEvaluator.Options` for evaluation.
554
+    ///
555
+    /// - Returns:           The `SecPolicy`.
556
+    /// - Throws:            An `AFError.serverTrustEvaluationFailed` error with reason `.revocationPolicyCreationFailed`
557
+    ///                      if the policy cannot be created.
558
+    static func revocation(options: RevocationTrustEvaluator.Options) throws -> SecPolicy {
559
+        guard let policy = SecPolicyCreateRevocation(options.rawValue) else {
560
+            throw AFError.serverTrustEvaluationFailed(reason: .revocationPolicyCreationFailed)
561
+        }
562
+
563
+        return policy
564
+    }
565
+}
566
+
567
+extension Array: AlamofireExtended {}
568
+public extension AlamofireExtension where ExtendedType == [SecCertificate] {
569
+    /// All `Data` values for the contained `SecCertificate`s.
570
+    var data: [Data] {
571
+        return type.map { SecCertificateCopyData($0) as Data }
572
+    }
573
+
574
+    /// All public `SecKey` values for the contained `SecCertificate`s.
575
+    var publicKeys: [SecKey] {
576
+        return type.compactMap { $0.af.publicKey }
577
+    }
578
+}
579
+
580
+extension SecCertificate: AlamofireExtended {}
581
+public extension AlamofireExtension where ExtendedType == SecCertificate {
582
+    /// The public key for `self`, if it can be extracted.
583
+    var publicKey: SecKey? {
584
+        let policy = SecPolicyCreateBasicX509()
585
+        var trust: SecTrust?
586
+        let trustCreationStatus = SecTrustCreateWithCertificates(type, policy, &trust)
587
+
588
+        guard let createdTrust = trust, trustCreationStatus == errSecSuccess else { return nil }
589
+
590
+        return SecTrustCopyPublicKey(createdTrust)
591
+    }
592
+}
593
+
594
+extension OSStatus: AlamofireExtended {}
595
+public extension AlamofireExtension where ExtendedType == OSStatus {
596
+    /// Returns whether `self` is `errSecSuccess`.
597
+    var isSuccess: Bool { return type == errSecSuccess }
598
+}
599
+
600
+extension SecTrustResultType: AlamofireExtended {}
601
+public extension AlamofireExtension where ExtendedType == SecTrustResultType {
602
+    /// Returns whether `self is `.unspecified` or `.proceed`.
603
+    var isSuccess: Bool {
604
+        return (type == .unspecified || type == .proceed)
605
+    }
606
+}

+ 1039
- 0
Pods/Alamofire/Source/Session.swift
File diff suppressed because it is too large
View File


+ 305
- 0
Pods/Alamofire/Source/SessionDelegate.swift View File

@@ -0,0 +1,305 @@
1
+//
2
+//  SessionDelegate.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
+/// Class which implements the various `URLSessionDelegate` methods to connect various Alamofire features.
28
+open class SessionDelegate: NSObject {
29
+    private let fileManager: FileManager
30
+
31
+    weak var stateProvider: SessionStateProvider?
32
+    var eventMonitor: EventMonitor?
33
+
34
+    /// Creates an instance from the given `FileManager`.
35
+    ///
36
+    /// - Parameter fileManager: `FileManager` to use for underlying file management, such as moving downloaded files.
37
+    ///                          `.default` by default.
38
+    public init(fileManager: FileManager = .default) {
39
+        self.fileManager = fileManager
40
+    }
41
+}
42
+
43
+/// Type which provides various `Session` state values.
44
+protocol SessionStateProvider: AnyObject {
45
+    var serverTrustManager: ServerTrustManager? { get }
46
+    var redirectHandler: RedirectHandler? { get }
47
+    var cachedResponseHandler: CachedResponseHandler? { get }
48
+
49
+    func request(for task: URLSessionTask) -> Request?
50
+    func didGatherMetricsForTask(_ task: URLSessionTask)
51
+    func didCompleteTask(_ task: URLSessionTask)
52
+    func credential(for task: URLSessionTask, in protectionSpace: URLProtectionSpace) -> URLCredential?
53
+    func cancelRequestsForSessionInvalidation(with error: Error?)
54
+}
55
+
56
+// MARK: URLSessionDelegate
57
+
58
+extension SessionDelegate: URLSessionDelegate {
59
+    open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
60
+        eventMonitor?.urlSession(session, didBecomeInvalidWithError: error)
61
+
62
+        stateProvider?.cancelRequestsForSessionInvalidation(with: error)
63
+    }
64
+}
65
+
66
+// MARK: URLSessionTaskDelegate
67
+
68
+extension SessionDelegate: URLSessionTaskDelegate {
69
+    /// Result of a `URLAuthenticationChallenge` evaluation.
70
+    typealias ChallengeEvaluation = (disposition: URLSession.AuthChallengeDisposition, credential: URLCredential?, error: AFError?)
71
+
72
+    open func urlSession(_ session: URLSession,
73
+                         task: URLSessionTask,
74
+                         didReceive challenge: URLAuthenticationChallenge,
75
+                         completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
76
+        eventMonitor?.urlSession(session, task: task, didReceive: challenge)
77
+
78
+        let evaluation: ChallengeEvaluation
79
+        switch challenge.protectionSpace.authenticationMethod {
80
+        case NSURLAuthenticationMethodServerTrust:
81
+            evaluation = attemptServerTrustAuthentication(with: challenge)
82
+        case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate:
83
+            evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
84
+        // case NSURLAuthenticationMethodClientCertificate:
85
+        // Alamofire doesn't currently support client certificate validation.
86
+        default:
87
+            evaluation = (.performDefaultHandling, nil, nil)
88
+        }
89
+
90
+        if let error = evaluation.error {
91
+            stateProvider?.request(for: task)?.didFailTask(task, earlyWithError: error)
92
+        }
93
+
94
+        completionHandler(evaluation.disposition, evaluation.credential)
95
+    }
96
+
97
+    /// Evaluates the server trust `URLAuthenticationChallenge` received.
98
+    ///
99
+    /// - Parameter challenge: The `URLAuthenticationChallenge`.
100
+    ///
101
+    /// - Returns:             The `ChallengeEvaluation`.
102
+    func attemptServerTrustAuthentication(with challenge: URLAuthenticationChallenge) -> ChallengeEvaluation {
103
+        let host = challenge.protectionSpace.host
104
+
105
+        guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
106
+            let trust = challenge.protectionSpace.serverTrust
107
+        else {
108
+            return (.performDefaultHandling, nil, nil)
109
+        }
110
+
111
+        do {
112
+            guard let evaluator = try stateProvider?.serverTrustManager?.serverTrustEvaluator(forHost: host) else {
113
+                return (.performDefaultHandling, nil, nil)
114
+            }
115
+
116
+            try evaluator.evaluate(trust, forHost: host)
117
+
118
+            return (.useCredential, URLCredential(trust: trust), nil)
119
+        } catch {
120
+            return (.cancelAuthenticationChallenge, nil, error.asAFError(or: .serverTrustEvaluationFailed(reason: .customEvaluationFailed(error: error))))
121
+        }
122
+    }
123
+
124
+    /// Evaluates the credential-based authentication `URLAuthenticationChallenge` received for `task`.
125
+    ///
126
+    /// - Parameters:
127
+    ///   - challenge: The `URLAuthenticationChallenge`.
128
+    ///   - task:      The `URLSessionTask` which received the challenge.
129
+    ///
130
+    /// - Returns:     The `ChallengeEvaluation`.
131
+    func attemptCredentialAuthentication(for challenge: URLAuthenticationChallenge,
132
+                                         belongingTo task: URLSessionTask) -> ChallengeEvaluation {
133
+        guard challenge.previousFailureCount == 0 else {
134
+            return (.rejectProtectionSpace, nil, nil)
135
+        }
136
+
137
+        guard let credential = stateProvider?.credential(for: task, in: challenge.protectionSpace) else {
138
+            return (.performDefaultHandling, nil, nil)
139
+        }
140
+
141
+        return (.useCredential, credential, nil)
142
+    }
143
+
144
+    open func urlSession(_ session: URLSession,
145
+                         task: URLSessionTask,
146
+                         didSendBodyData bytesSent: Int64,
147
+                         totalBytesSent: Int64,
148
+                         totalBytesExpectedToSend: Int64) {
149
+        eventMonitor?.urlSession(session,
150
+                                 task: task,
151
+                                 didSendBodyData: bytesSent,
152
+                                 totalBytesSent: totalBytesSent,
153
+                                 totalBytesExpectedToSend: totalBytesExpectedToSend)
154
+
155
+        stateProvider?.request(for: task)?.updateUploadProgress(totalBytesSent: totalBytesSent,
156
+                                                                totalBytesExpectedToSend: totalBytesExpectedToSend)
157
+    }
158
+
159
+    open func urlSession(_ session: URLSession,
160
+                         task: URLSessionTask,
161
+                         needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) {
162
+        eventMonitor?.urlSession(session, taskNeedsNewBodyStream: task)
163
+
164
+        guard let request = stateProvider?.request(for: task) as? UploadRequest else {
165
+            fatalError("needNewBodyStream for request that isn't UploadRequest.")
166
+        }
167
+
168
+        completionHandler(request.inputStream())
169
+    }
170
+
171
+    open func urlSession(_ session: URLSession,
172
+                         task: URLSessionTask,
173
+                         willPerformHTTPRedirection response: HTTPURLResponse,
174
+                         newRequest request: URLRequest,
175
+                         completionHandler: @escaping (URLRequest?) -> Void) {
176
+        eventMonitor?.urlSession(session, task: task, willPerformHTTPRedirection: response, newRequest: request)
177
+
178
+        if let redirectHandler = stateProvider?.request(for: task)?.redirectHandler ?? stateProvider?.redirectHandler {
179
+            redirectHandler.task(task, willBeRedirectedTo: request, for: response, completion: completionHandler)
180
+        } else {
181
+            completionHandler(request)
182
+        }
183
+    }
184
+
185
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
186
+        eventMonitor?.urlSession(session, task: task, didFinishCollecting: metrics)
187
+
188
+        stateProvider?.request(for: task)?.didGatherMetrics(metrics)
189
+
190
+        stateProvider?.didGatherMetricsForTask(task)
191
+    }
192
+
193
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
194
+        eventMonitor?.urlSession(session, task: task, didCompleteWithError: error)
195
+
196
+        stateProvider?.request(for: task)?.didCompleteTask(task, with: error.map { $0.asAFError(or: .sessionTaskFailed(error: $0)) })
197
+
198
+        stateProvider?.didCompleteTask(task)
199
+    }
200
+
201
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
202
+    open func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
203
+        eventMonitor?.urlSession(session, taskIsWaitingForConnectivity: task)
204
+    }
205
+}
206
+
207
+// MARK: URLSessionDataDelegate
208
+
209
+extension SessionDelegate: URLSessionDataDelegate {
210
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
211
+        eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: data)
212
+
213
+        guard let request = stateProvider?.request(for: dataTask) as? DataRequest else {
214
+            fatalError("dataTask received data for incorrect Request subclass: \(String(describing: stateProvider?.request(for: dataTask)))")
215
+        }
216
+
217
+        request.didReceive(data: data)
218
+    }
219
+
220
+    open func urlSession(_ session: URLSession,
221
+                         dataTask: URLSessionDataTask,
222
+                         willCacheResponse proposedResponse: CachedURLResponse,
223
+                         completionHandler: @escaping (CachedURLResponse?) -> Void) {
224
+        eventMonitor?.urlSession(session, dataTask: dataTask, willCacheResponse: proposedResponse)
225
+
226
+        if let handler = stateProvider?.request(for: dataTask)?.cachedResponseHandler ?? stateProvider?.cachedResponseHandler {
227
+            handler.dataTask(dataTask, willCacheResponse: proposedResponse, completion: completionHandler)
228
+        } else {
229
+            completionHandler(proposedResponse)
230
+        }
231
+    }
232
+}
233
+
234
+// MARK: URLSessionDownloadDelegate
235
+
236
+extension SessionDelegate: URLSessionDownloadDelegate {
237
+    open func urlSession(_ session: URLSession,
238
+                         downloadTask: URLSessionDownloadTask,
239
+                         didResumeAtOffset fileOffset: Int64,
240
+                         expectedTotalBytes: Int64) {
241
+        eventMonitor?.urlSession(session,
242
+                                 downloadTask: downloadTask,
243
+                                 didResumeAtOffset: fileOffset,
244
+                                 expectedTotalBytes: expectedTotalBytes)
245
+
246
+        guard let downloadRequest = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
247
+            fatalError("No DownloadRequest found for downloadTask: \(downloadTask)")
248
+        }
249
+
250
+        downloadRequest.updateDownloadProgress(bytesWritten: fileOffset,
251
+                                               totalBytesExpectedToWrite: expectedTotalBytes)
252
+    }
253
+
254
+    open func urlSession(_ session: URLSession,
255
+                         downloadTask: URLSessionDownloadTask,
256
+                         didWriteData bytesWritten: Int64,
257
+                         totalBytesWritten: Int64,
258
+                         totalBytesExpectedToWrite: Int64) {
259
+        eventMonitor?.urlSession(session,
260
+                                 downloadTask: downloadTask,
261
+                                 didWriteData: bytesWritten,
262
+                                 totalBytesWritten: totalBytesWritten,
263
+                                 totalBytesExpectedToWrite: totalBytesExpectedToWrite)
264
+
265
+        guard let downloadRequest = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
266
+            fatalError("No DownloadRequest found for downloadTask: \(downloadTask)")
267
+        }
268
+
269
+        downloadRequest.updateDownloadProgress(bytesWritten: bytesWritten,
270
+                                               totalBytesExpectedToWrite: totalBytesExpectedToWrite)
271
+    }
272
+
273
+    open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
274
+        eventMonitor?.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
275
+
276
+        guard let request = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
277
+            fatalError("Download finished but either no request found or request wasn't DownloadRequest")
278
+        }
279
+
280
+        guard let response = request.response else {
281
+            fatalError("URLSessionDownloadTask finished downloading with no response.")
282
+        }
283
+
284
+        let (destination, options) = (request.destination)(location, response)
285
+
286
+        eventMonitor?.request(request, didCreateDestinationURL: destination)
287
+
288
+        do {
289
+            if options.contains(.removePreviousFile), fileManager.fileExists(atPath: destination.path) {
290
+                try fileManager.removeItem(at: destination)
291
+            }
292
+
293
+            if options.contains(.createIntermediateDirectories) {
294
+                let directory = destination.deletingLastPathComponent()
295
+                try fileManager.createDirectory(at: directory, withIntermediateDirectories: true)
296
+            }
297
+
298
+            try fileManager.moveItem(at: location, to: destination)
299
+
300
+            request.didFinishDownloading(using: downloadTask, with: .success(destination))
301
+        } catch {
302
+            request.didFinishDownloading(using: downloadTask, with: .failure(.downloadedFileMoveFailed(error: error, source: location, destination: destination)))
303
+        }
304
+    }
305
+}

+ 105
- 0
Pods/Alamofire/Source/URLConvertible+URLRequestConvertible.swift View File

@@ -0,0 +1,105 @@
1
+//
2
+//  URLConvertible+URLRequestConvertible.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
+/// Types adopting the `URLConvertible` protocol can be used to construct `URL`s, which can then be used to construct
28
+/// `URLRequests`.
29
+public protocol URLConvertible {
30
+    /// Returns a `URL` from the conforming instance or throws.
31
+    ///
32
+    /// - Returns: The `URL` created from the instance.
33
+    /// - Throws:  Any error thrown while creating the `URL`.
34
+    func asURL() throws -> URL
35
+}
36
+
37
+extension String: URLConvertible {
38
+    /// Returns a `URL` if `self` can be used to initialize a `URL` instance, otherwise throws.
39
+    ///
40
+    /// - Returns: The `URL` initialized with `self`.
41
+    /// - Throws:  An `AFError.invalidURL` instance.
42
+    public func asURL() throws -> URL {
43
+        guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }
44
+
45
+        return url
46
+    }
47
+}
48
+
49
+extension URL: URLConvertible {
50
+    /// Returns `self`.
51
+    public func asURL() throws -> URL { return self }
52
+}
53
+
54
+extension URLComponents: URLConvertible {
55
+    /// Returns a `URL` if the `self`'s `url` is not nil, otherwise throws.
56
+    ///
57
+    /// - Returns: The `URL` from the `url` property.
58
+    /// - Throws:  An `AFError.invalidURL` instance.
59
+    public func asURL() throws -> URL {
60
+        guard let url = url else { throw AFError.invalidURL(url: self) }
61
+
62
+        return url
63
+    }
64
+}
65
+
66
+// MARK: -
67
+
68
+/// Types adopting the `URLRequestConvertible` protocol can be used to safely construct `URLRequest`s.
69
+public protocol URLRequestConvertible {
70
+    /// Returns a `URLRequest` or throws if an `Error` was encountered.
71
+    ///
72
+    /// - Returns: A `URLRequest`.
73
+    /// - Throws:  Any error thrown while constructing the `URLRequest`.
74
+    func asURLRequest() throws -> URLRequest
75
+}
76
+
77
+extension URLRequestConvertible {
78
+    /// The `URLRequest` returned by discarding any `Error` encountered.
79
+    public var urlRequest: URLRequest? { return try? asURLRequest() }
80
+}
81
+
82
+extension URLRequest: URLRequestConvertible {
83
+    /// Returns `self`.
84
+    public func asURLRequest() throws -> URLRequest { return self }
85
+}
86
+
87
+// MARK: -
88
+
89
+extension URLRequest {
90
+    /// Creates an instance with the specified `url`, `method`, and `headers`.
91
+    ///
92
+    /// - Parameters:
93
+    ///   - url:     The `URLConvertible` value.
94
+    ///   - method:  The `HTTPMethod`.
95
+    ///   - headers: The `HTTPHeaders`, `nil` by default.
96
+    /// - Throws:    Any error thrown while converting the `URLConvertible` to a `URL`.
97
+    public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws {
98
+        let url = try url.asURL()
99
+
100
+        self.init(url: url)
101
+
102
+        httpMethod = method.rawValue
103
+        allHTTPHeaderFields = headers?.dictionary
104
+    }
105
+}

+ 973
- 0
Pods/Alamofire/Source/URLEncodedFormEncoder.swift View File

@@ -0,0 +1,973 @@
1
+//
2
+//  URLEncodedFormEncoder.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
+/// An object that encodes instances into URL-encoded query strings.
28
+///
29
+/// There is no published specification for how to encode collection types. By default, the convention of appending
30
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
31
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
32
+/// square brackets appended to array keys.
33
+///
34
+/// `BoolEncoding` can be used to configure how `Bool` values are encoded. The default behavior is to encode
35
+/// `true` as 1 and `false` as 0.
36
+///
37
+/// `DateEncoding` can be used to configure how `Date` values are encoded. By default, the `.deferredToDate`
38
+/// strategy is used, which formats dates from their structure.
39
+///
40
+/// `SpaceEncoding` can be used to configure how spaces are encoded. Modern encodings use percent replacement (`%20`),
41
+/// while older encodings may expect spaces to be replaced with `+`.
42
+///
43
+/// This type is largely based on Vapor's [`url-encoded-form`](https://github.com/vapor/url-encoded-form) project.
44
+public final class URLEncodedFormEncoder {
45
+    /// Encoding to use for `Array` values.
46
+    public enum ArrayEncoding {
47
+        /// An empty set of square brackets ("[]") are appended to the key for every value. This is the default encoding.
48
+        case brackets
49
+        /// No brackets are appended to the key and the key is encoded as is.
50
+        case noBrackets
51
+
52
+        /// Encodes the key according to the encoding.
53
+        ///
54
+        /// - Parameter key: The `key` to encode.
55
+        /// - Returns:       The encoded key.
56
+        func encode(_ key: String) -> String {
57
+            switch self {
58
+            case .brackets: return "\(key)[]"
59
+            case .noBrackets: return key
60
+            }
61
+        }
62
+    }
63
+
64
+    /// Encoding to use for `Bool` values.
65
+    public enum BoolEncoding {
66
+        /// Encodes `true` as `1`, `false` as `0`.
67
+        case numeric
68
+        /// Encodes `true` as "true", `false` as "false". This is the default encoding.
69
+        case literal
70
+
71
+        /// Encodes the given `Bool` as a `String`.
72
+        ///
73
+        /// - Parameter value: The `Bool` to encode.
74
+        ///
75
+        /// - Returns:         The encoded `String`.
76
+        func encode(_ value: Bool) -> String {
77
+            switch self {
78
+            case .numeric: return value ? "1" : "0"
79
+            case .literal: return value ? "true" : "false"
80
+            }
81
+        }
82
+    }
83
+
84
+    /// Encoding to use for `Data` values.
85
+    public enum DataEncoding {
86
+        /// Defers encoding to the `Data` type.
87
+        case deferredToData
88
+        /// Encodes `Data` as a Base64-encoded string. This is the default encoding.
89
+        case base64
90
+        /// Encode the `Data` as a custom value encoded by the given closure.
91
+        case custom((Data) throws -> String)
92
+
93
+        /// Encodes `Data` according to the encoding.
94
+        ///
95
+        /// - Parameter data: The `Data` to encode.
96
+        ///
97
+        /// - Returns:        The encoded `String`, or `nil` if the `Data` should be encoded according to its
98
+        ///                   `Encodable` implementation.
99
+        func encode(_ data: Data) throws -> String? {
100
+            switch self {
101
+            case .deferredToData: return nil
102
+            case .base64: return data.base64EncodedString()
103
+            case let .custom(encoding): return try encoding(data)
104
+            }
105
+        }
106
+    }
107
+
108
+    /// Encoding to use for `Date` values.
109
+    public enum DateEncoding {
110
+        /// ISO8601 and RFC3339 formatter.
111
+        private static let iso8601Formatter: ISO8601DateFormatter = {
112
+            let formatter = ISO8601DateFormatter()
113
+            formatter.formatOptions = .withInternetDateTime
114
+            return formatter
115
+        }()
116
+
117
+        /// Defers encoding to the `Date` type. This is the default encoding.
118
+        case deferredToDate
119
+        /// Encodes `Date`s as seconds since midnight UTC on January 1, 1970.
120
+        case secondsSince1970
121
+        /// Encodes `Date`s as milliseconds since midnight UTC on January 1, 1970.
122
+        case millisecondsSince1970
123
+        /// Encodes `Date`s according to the ISO8601 and RFC3339 standards.
124
+        case iso8601
125
+        /// Encodes `Date`s using the given `DateFormatter`.
126
+        case formatted(DateFormatter)
127
+        /// Encodes `Date`s using the given closure.
128
+        case custom((Date) throws -> String)
129
+
130
+        /// Encodes the date according to the encoding.
131
+        ///
132
+        /// - Parameter date: The `Date` to encode.
133
+        ///
134
+        /// - Returns:        The encoded `String`, or `nil` if the `Date` should be encoded according to its
135
+        ///                   `Encodable` implementation.
136
+        func encode(_ date: Date) throws -> String? {
137
+            switch self {
138
+            case .deferredToDate:
139
+                return nil
140
+            case .secondsSince1970:
141
+                return String(date.timeIntervalSince1970)
142
+            case .millisecondsSince1970:
143
+                return String(date.timeIntervalSince1970 * 1000.0)
144
+            case .iso8601:
145
+                return DateEncoding.iso8601Formatter.string(from: date)
146
+            case let .formatted(formatter):
147
+                return formatter.string(from: date)
148
+            case let .custom(closure):
149
+                return try closure(date)
150
+            }
151
+        }
152
+    }
153
+
154
+    /// Encoding to use for keys.
155
+    ///
156
+    /// This type is derived from [`JSONEncoder`'s `KeyEncodingStrategy`](https://github.com/apple/swift/blob/6aa313b8dd5f05135f7f878eccc1db6f9fbe34ff/stdlib/public/Darwin/Foundation/JSONEncoder.swift#L128)
157
+    /// and [`XMLEncoder`s `KeyEncodingStrategy`](https://github.com/MaxDesiatov/XMLCoder/blob/master/Sources/XMLCoder/Encoder/XMLEncoder.swift#L102).
158
+    public enum KeyEncoding {
159
+        /// Use the keys specified by each type. This is the default encoding.
160
+        case useDefaultKeys
161
+        /// Convert from "camelCaseKeys" to "snake_case_keys" before writing a key.
162
+        ///
163
+        /// Capital characters are determined by testing membership in
164
+        /// `CharacterSet.uppercaseLetters` and `CharacterSet.lowercaseLetters`
165
+        /// (Unicode General Categories Lu and Lt).
166
+        /// The conversion to lower case uses `Locale.system`, also known as
167
+        /// the ICU "root" locale. This means the result is consistent
168
+        /// regardless of the current user's locale and language preferences.
169
+        ///
170
+        /// Converting from camel case to snake case:
171
+        /// 1. Splits words at the boundary of lower-case to upper-case
172
+        /// 2. Inserts `_` between words
173
+        /// 3. Lowercases the entire string
174
+        /// 4. Preserves starting and ending `_`.
175
+        ///
176
+        /// For example, `oneTwoThree` becomes `one_two_three`. `_oneTwoThree_` becomes `_one_two_three_`.
177
+        ///
178
+        /// - Note: Using a key encoding strategy has a nominal performance cost, as each string key has to be converted.
179
+        case convertToSnakeCase
180
+        /// Same as convertToSnakeCase, but using `-` instead of `_`.
181
+        /// For example `oneTwoThree` becomes `one-two-three`.
182
+        case convertToKebabCase
183
+        /// Capitalize the first letter only.
184
+        /// For example `oneTwoThree` becomes  `OneTwoThree`.
185
+        case capitalized
186
+        /// Uppercase all letters.
187
+        /// For example `oneTwoThree` becomes  `ONETWOTHREE`.
188
+        case uppercased
189
+        /// Lowercase all letters.
190
+        /// For example `oneTwoThree` becomes  `onetwothree`.
191
+        case lowercased
192
+        /// A custom encoding using the provided closure.
193
+        case custom((String) -> String)
194
+
195
+        func encode(_ key: String) -> String {
196
+            switch self {
197
+            case .useDefaultKeys: return key
198
+            case .convertToSnakeCase: return convertToSnakeCase(key)
199
+            case .convertToKebabCase: return convertToKebabCase(key)
200
+            case .capitalized: return String(key.prefix(1).uppercased() + key.dropFirst())
201
+            case .uppercased: return key.uppercased()
202
+            case .lowercased: return key.lowercased()
203
+            case let .custom(encoding): return encoding(key)
204
+            }
205
+        }
206
+
207
+        private func convertToSnakeCase(_ key: String) -> String {
208
+            return convert(key, usingSeparator: "_")
209
+        }
210
+
211
+        private func convertToKebabCase(_ key: String) -> String {
212
+            return convert(key, usingSeparator: "-")
213
+        }
214
+
215
+        private func convert(_ key: String, usingSeparator separator: String) -> String {
216
+            guard !key.isEmpty else { return key }
217
+
218
+            var words: [Range<String.Index>] = []
219
+            // The general idea of this algorithm is to split words on
220
+            // transition from lower to upper case, then on transition of >1
221
+            // upper case characters to lowercase
222
+            //
223
+            // myProperty -> my_property
224
+            // myURLProperty -> my_url_property
225
+            //
226
+            // It is assumed, per Swift naming conventions, that the first character of the key is lowercase.
227
+            var wordStart = key.startIndex
228
+            var searchRange = key.index(after: wordStart)..<key.endIndex
229
+
230
+            // Find next uppercase character
231
+            while let upperCaseRange = key.rangeOfCharacter(from: CharacterSet.uppercaseLetters, options: [], range: searchRange) {
232
+                let untilUpperCase = wordStart..<upperCaseRange.lowerBound
233
+                words.append(untilUpperCase)
234
+
235
+                // Find next lowercase character
236
+                searchRange = upperCaseRange.lowerBound..<searchRange.upperBound
237
+                guard let lowerCaseRange = key.rangeOfCharacter(from: CharacterSet.lowercaseLetters, options: [], range: searchRange) else {
238
+                    // There are no more lower case letters. Just end here.
239
+                    wordStart = searchRange.lowerBound
240
+                    break
241
+                }
242
+
243
+                // Is the next lowercase letter more than 1 after the uppercase?
244
+                // If so, we encountered a group of uppercase letters that we
245
+                // should treat as its own word
246
+                let nextCharacterAfterCapital = key.index(after: upperCaseRange.lowerBound)
247
+                if lowerCaseRange.lowerBound == nextCharacterAfterCapital {
248
+                    // The next character after capital is a lower case character and therefore not a word boundary.
249
+                    // Continue searching for the next upper case for the boundary.
250
+                    wordStart = upperCaseRange.lowerBound
251
+                } else {
252
+                    // There was a range of >1 capital letters. Turn those into a word, stopping at the capital before the lower case character.
253
+                    let beforeLowerIndex = key.index(before: lowerCaseRange.lowerBound)
254
+                    words.append(upperCaseRange.lowerBound..<beforeLowerIndex)
255
+
256
+                    // Next word starts at the capital before the lowercase we just found
257
+                    wordStart = beforeLowerIndex
258
+                }
259
+                searchRange = lowerCaseRange.upperBound..<searchRange.upperBound
260
+            }
261
+            words.append(wordStart..<searchRange.upperBound)
262
+            let result = words.map { range in
263
+                key[range].lowercased()
264
+            }.joined(separator: separator)
265
+
266
+            return result
267
+        }
268
+    }
269
+
270
+    /// Encoding to use for spaces.
271
+    public enum SpaceEncoding {
272
+        /// Encodes spaces according to normal percent escaping rules (%20).
273
+        case percentEscaped
274
+        /// Encodes spaces as `+`,
275
+        case plusReplaced
276
+
277
+        /// Encodes the string according to the encoding.
278
+        ///
279
+        /// - Parameter string: The `String` to encode.
280
+        ///
281
+        /// - Returns:          The encoded `String`.
282
+        func encode(_ string: String) -> String {
283
+            switch self {
284
+            case .percentEscaped: return string.replacingOccurrences(of: " ", with: "%20")
285
+            case .plusReplaced: return string.replacingOccurrences(of: " ", with: "+")
286
+            }
287
+        }
288
+    }
289
+
290
+    /// `URLEncodedFormEncoder` error.
291
+    public enum Error: Swift.Error {
292
+        /// An invalid root object was created by the encoder. Only keyed values are valid.
293
+        case invalidRootObject(String)
294
+
295
+        var localizedDescription: String {
296
+            switch self {
297
+            case let .invalidRootObject(object):
298
+                return "URLEncodedFormEncoder requires keyed root object. Received \(object) instead."
299
+            }
300
+        }
301
+    }
302
+
303
+    /// Whether or not to sort the encoded key value pairs.
304
+    ///
305
+    /// - Note: This setting ensures a consistent ordering for all encodings of the same parameters. When set to `false`,
306
+    ///         encoded `Dictionary` values may have a different encoded order each time they're encoded due to
307
+    ///       ` Dictionary`'s random storage order, but `Encodable` types will maintain their encoded order.
308
+    public let alphabetizeKeyValuePairs: Bool
309
+    /// The `ArrayEncoding` to use.
310
+    public let arrayEncoding: ArrayEncoding
311
+    /// The `BoolEncoding` to use.
312
+    public let boolEncoding: BoolEncoding
313
+    /// THe `DataEncoding` to use.
314
+    public let dataEncoding: DataEncoding
315
+    /// The `DateEncoding` to use.
316
+    public let dateEncoding: DateEncoding
317
+    /// The `KeyEncoding` to use.
318
+    public let keyEncoding: KeyEncoding
319
+    /// The `SpaceEncoding` to use.
320
+    public let spaceEncoding: SpaceEncoding
321
+    /// The `CharacterSet` of allowed (non-escaped) characters.
322
+    public var allowedCharacters: CharacterSet
323
+
324
+    /// Creates an instance from the supplied parameters.
325
+    ///
326
+    /// - Parameters:
327
+    ///   - alphabetizeKeyValuePairs: Whether or not to sort the encoded key value pairs. `true` by default.
328
+    ///   - arrayEncoding:            The `ArrayEncoding` to use. `.brackets` by default.
329
+    ///   - boolEncoding:             The `BoolEncoding` to use. `.numeric` by default.
330
+    ///   - dataEncoding:             The `DataEncoding` to use. `.base64` by default.
331
+    ///   - dateEncoding:             The `DateEncoding` to use. `.deferredToDate` by default.
332
+    ///   - keyEncoding:              The `KeyEncoding` to use. `.useDefaultKeys` by default.
333
+    ///   - spaceEncoding:            The `SpaceEncoding` to use. `.percentEscaped` by default.
334
+    ///   - allowedCharacters:        The `CharacterSet` of allowed (non-escaped) characters. `.afURLQueryAllowed` by
335
+    ///                               default.
336
+    public init(alphabetizeKeyValuePairs: Bool = true,
337
+                arrayEncoding: ArrayEncoding = .brackets,
338
+                boolEncoding: BoolEncoding = .numeric,
339
+                dataEncoding: DataEncoding = .base64,
340
+                dateEncoding: DateEncoding = .deferredToDate,
341
+                keyEncoding: KeyEncoding = .useDefaultKeys,
342
+                spaceEncoding: SpaceEncoding = .percentEscaped,
343
+                allowedCharacters: CharacterSet = .afURLQueryAllowed) {
344
+        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs
345
+        self.arrayEncoding = arrayEncoding
346
+        self.boolEncoding = boolEncoding
347
+        self.dataEncoding = dataEncoding
348
+        self.dateEncoding = dateEncoding
349
+        self.keyEncoding = keyEncoding
350
+        self.spaceEncoding = spaceEncoding
351
+        self.allowedCharacters = allowedCharacters
352
+    }
353
+
354
+    func encode(_ value: Encodable) throws -> URLEncodedFormComponent {
355
+        let context = URLEncodedFormContext(.object([]))
356
+        let encoder = _URLEncodedFormEncoder(context: context,
357
+                                             boolEncoding: boolEncoding,
358
+                                             dataEncoding: dataEncoding,
359
+                                             dateEncoding: dateEncoding)
360
+        try value.encode(to: encoder)
361
+
362
+        return context.component
363
+    }
364
+
365
+    /// Encodes the `value` as a URL form encoded `String`.
366
+    ///
367
+    /// - Parameter value: The `Encodable` value.`
368
+    ///
369
+    /// - Returns:         The encoded `String`.
370
+    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.
371
+    public func encode(_ value: Encodable) throws -> String {
372
+        let component: URLEncodedFormComponent = try encode(value)
373
+
374
+        guard case let .object(object) = component else {
375
+            throw Error.invalidRootObject("\(component)")
376
+        }
377
+
378
+        let serializer = URLEncodedFormSerializer(alphabetizeKeyValuePairs: alphabetizeKeyValuePairs,
379
+                                                  arrayEncoding: arrayEncoding,
380
+                                                  keyEncoding: keyEncoding,
381
+                                                  spaceEncoding: spaceEncoding,
382
+                                                  allowedCharacters: allowedCharacters)
383
+        let query = serializer.serialize(object)
384
+
385
+        return query
386
+    }
387
+
388
+    /// Encodes the value as `Data`. This is performed by first creating an encoded `String` and then returning the
389
+    /// `.utf8` data.
390
+    ///
391
+    /// - Parameter value: The `Encodable` value.
392
+    ///
393
+    /// - Returns:         The encoded `Data`.
394
+    ///
395
+    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.
396
+    public func encode(_ value: Encodable) throws -> Data {
397
+        let string: String = try encode(value)
398
+
399
+        return Data(string.utf8)
400
+    }
401
+}
402
+
403
+final class _URLEncodedFormEncoder {
404
+    var codingPath: [CodingKey]
405
+    // Returns an empty dictionary, as this encoder doesn't support userInfo.
406
+    var userInfo: [CodingUserInfoKey: Any] { return [:] }
407
+
408
+    let context: URLEncodedFormContext
409
+
410
+    private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
411
+    private let dataEncoding: URLEncodedFormEncoder.DataEncoding
412
+    private let dateEncoding: URLEncodedFormEncoder.DateEncoding
413
+
414
+    public init(context: URLEncodedFormContext,
415
+                codingPath: [CodingKey] = [],
416
+                boolEncoding: URLEncodedFormEncoder.BoolEncoding,
417
+                dataEncoding: URLEncodedFormEncoder.DataEncoding,
418
+                dateEncoding: URLEncodedFormEncoder.DateEncoding) {
419
+        self.context = context
420
+        self.codingPath = codingPath
421
+        self.boolEncoding = boolEncoding
422
+        self.dataEncoding = dataEncoding
423
+        self.dateEncoding = dateEncoding
424
+    }
425
+}
426
+
427
+extension _URLEncodedFormEncoder: Encoder {
428
+    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
429
+        let container = _URLEncodedFormEncoder.KeyedContainer<Key>(context: context,
430
+                                                                   codingPath: codingPath,
431
+                                                                   boolEncoding: boolEncoding,
432
+                                                                   dataEncoding: dataEncoding,
433
+                                                                   dateEncoding: dateEncoding)
434
+        return KeyedEncodingContainer(container)
435
+    }
436
+
437
+    func unkeyedContainer() -> UnkeyedEncodingContainer {
438
+        return _URLEncodedFormEncoder.UnkeyedContainer(context: context,
439
+                                                       codingPath: codingPath,
440
+                                                       boolEncoding: boolEncoding,
441
+                                                       dataEncoding: dataEncoding,
442
+                                                       dateEncoding: dateEncoding)
443
+    }
444
+
445
+    func singleValueContainer() -> SingleValueEncodingContainer {
446
+        return _URLEncodedFormEncoder.SingleValueContainer(context: context,
447
+                                                           codingPath: codingPath,
448
+                                                           boolEncoding: boolEncoding,
449
+                                                           dataEncoding: dataEncoding,
450
+                                                           dateEncoding: dateEncoding)
451
+    }
452
+}
453
+
454
+final class URLEncodedFormContext {
455
+    var component: URLEncodedFormComponent
456
+
457
+    init(_ component: URLEncodedFormComponent) {
458
+        self.component = component
459
+    }
460
+}
461
+
462
+enum URLEncodedFormComponent {
463
+    typealias Object = [(key: String, value: URLEncodedFormComponent)]
464
+
465
+    case string(String)
466
+    case array([URLEncodedFormComponent])
467
+    case object(Object)
468
+
469
+    /// Converts self to an `[URLEncodedFormData]` or returns `nil` if not convertible.
470
+    var array: [URLEncodedFormComponent]? {
471
+        switch self {
472
+        case let .array(array): return array
473
+        default: return nil
474
+        }
475
+    }
476
+
477
+    /// Converts self to an `Object` or returns `nil` if not convertible.
478
+    var object: Object? {
479
+        switch self {
480
+        case let .object(object): return object
481
+        default: return nil
482
+        }
483
+    }
484
+
485
+    /// Sets self to the supplied value at a given path.
486
+    ///
487
+    ///     data.set(to: "hello", at: ["path", "to", "value"])
488
+    ///
489
+    /// - parameters:
490
+    ///     - value: Value of `Self` to set at the supplied path.
491
+    ///     - path: `CodingKey` path to update with the supplied value.
492
+    public mutating func set(to value: URLEncodedFormComponent, at path: [CodingKey]) {
493
+        set(&self, to: value, at: path)
494
+    }
495
+
496
+    /// Recursive backing method to `set(to:at:)`.
497
+    private func set(_ context: inout URLEncodedFormComponent, to value: URLEncodedFormComponent, at path: [CodingKey]) {
498
+        guard path.count >= 1 else {
499
+            context = value
500
+            return
501
+        }
502
+
503
+        let end = path[0]
504
+        var child: URLEncodedFormComponent
505
+        switch path.count {
506
+        case 1:
507
+            child = value
508
+        case 2...:
509
+            if let index = end.intValue {
510
+                let array = context.array ?? []
511
+                if array.count > index {
512
+                    child = array[index]
513
+                } else {
514
+                    child = .array([])
515
+                }
516
+                set(&child, to: value, at: Array(path[1...]))
517
+            } else {
518
+                child = context.object?.first { $0.key == end.stringValue }?.value ?? .object(.init())
519
+                set(&child, to: value, at: Array(path[1...]))
520
+            }
521
+        default: fatalError("Unreachable")
522
+        }
523
+
524
+        if let index = end.intValue {
525
+            if var array = context.array {
526
+                if array.count > index {
527
+                    array[index] = child
528
+                } else {
529
+                    array.append(child)
530
+                }
531
+                context = .array(array)
532
+            } else {
533
+                context = .array([child])
534
+            }
535
+        } else {
536
+            if var object = context.object {
537
+                if let index = object.firstIndex(where: { $0.key == end.stringValue }) {
538
+                    object[index] = (key: end.stringValue, value: child)
539
+                } else {
540
+                    object.append((key: end.stringValue, value: child))
541
+                }
542
+                context = .object(object)
543
+            } else {
544
+                context = .object([(key: end.stringValue, value: child)])
545
+            }
546
+        }
547
+    }
548
+}
549
+
550
+struct AnyCodingKey: CodingKey, Hashable {
551
+    let stringValue: String
552
+    let intValue: Int?
553
+
554
+    init?(stringValue: String) {
555
+        self.stringValue = stringValue
556
+        intValue = nil
557
+    }
558
+
559
+    init?(intValue: Int) {
560
+        stringValue = "\(intValue)"
561
+        self.intValue = intValue
562
+    }
563
+
564
+    init<Key>(_ base: Key) where Key: CodingKey {
565
+        if let intValue = base.intValue {
566
+            self.init(intValue: intValue)!
567
+        } else {
568
+            self.init(stringValue: base.stringValue)!
569
+        }
570
+    }
571
+}
572
+
573
+extension _URLEncodedFormEncoder {
574
+    final class KeyedContainer<Key> where Key: CodingKey {
575
+        var codingPath: [CodingKey]
576
+
577
+        private let context: URLEncodedFormContext
578
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
579
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
580
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
581
+
582
+        init(context: URLEncodedFormContext,
583
+             codingPath: [CodingKey],
584
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
585
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
586
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
587
+            self.context = context
588
+            self.codingPath = codingPath
589
+            self.boolEncoding = boolEncoding
590
+            self.dataEncoding = dataEncoding
591
+            self.dateEncoding = dateEncoding
592
+        }
593
+
594
+        private func nestedCodingPath(for key: CodingKey) -> [CodingKey] {
595
+            return codingPath + [key]
596
+        }
597
+    }
598
+}
599
+
600
+extension _URLEncodedFormEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
601
+    func encodeNil(forKey key: Key) throws {
602
+        let context = EncodingError.Context(codingPath: codingPath,
603
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
604
+        throw EncodingError.invalidValue("\(key): nil", context)
605
+    }
606
+
607
+    func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
608
+        var container = nestedSingleValueEncoder(for: key)
609
+        try container.encode(value)
610
+    }
611
+
612
+    func nestedSingleValueEncoder(for key: Key) -> SingleValueEncodingContainer {
613
+        let container = _URLEncodedFormEncoder.SingleValueContainer(context: context,
614
+                                                                    codingPath: nestedCodingPath(for: key),
615
+                                                                    boolEncoding: boolEncoding,
616
+                                                                    dataEncoding: dataEncoding,
617
+                                                                    dateEncoding: dateEncoding)
618
+
619
+        return container
620
+    }
621
+
622
+    func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
623
+        let container = _URLEncodedFormEncoder.UnkeyedContainer(context: context,
624
+                                                                codingPath: nestedCodingPath(for: key),
625
+                                                                boolEncoding: boolEncoding,
626
+                                                                dataEncoding: dataEncoding,
627
+                                                                dateEncoding: dateEncoding)
628
+
629
+        return container
630
+    }
631
+
632
+    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
633
+        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,
634
+                                                                         codingPath: nestedCodingPath(for: key),
635
+                                                                         boolEncoding: boolEncoding,
636
+                                                                         dataEncoding: dataEncoding,
637
+                                                                         dateEncoding: dateEncoding)
638
+
639
+        return KeyedEncodingContainer(container)
640
+    }
641
+
642
+    func superEncoder() -> Encoder {
643
+        return _URLEncodedFormEncoder(context: context,
644
+                                      codingPath: codingPath,
645
+                                      boolEncoding: boolEncoding,
646
+                                      dataEncoding: dataEncoding,
647
+                                      dateEncoding: dateEncoding)
648
+    }
649
+
650
+    func superEncoder(forKey key: Key) -> Encoder {
651
+        return _URLEncodedFormEncoder(context: context,
652
+                                      codingPath: nestedCodingPath(for: key),
653
+                                      boolEncoding: boolEncoding,
654
+                                      dataEncoding: dataEncoding,
655
+                                      dateEncoding: dateEncoding)
656
+    }
657
+}
658
+
659
+extension _URLEncodedFormEncoder {
660
+    final class SingleValueContainer {
661
+        var codingPath: [CodingKey]
662
+
663
+        private var canEncodeNewValue = true
664
+
665
+        private let context: URLEncodedFormContext
666
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
667
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
668
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
669
+
670
+        init(context: URLEncodedFormContext,
671
+             codingPath: [CodingKey],
672
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
673
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
674
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
675
+            self.context = context
676
+            self.codingPath = codingPath
677
+            self.boolEncoding = boolEncoding
678
+            self.dataEncoding = dataEncoding
679
+            self.dateEncoding = dateEncoding
680
+        }
681
+
682
+        private func checkCanEncode(value: Any?) throws {
683
+            guard canEncodeNewValue else {
684
+                let context = EncodingError.Context(codingPath: codingPath,
685
+                                                    debugDescription: "Attempt to encode value through single value container when previously value already encoded.")
686
+                throw EncodingError.invalidValue(value as Any, context)
687
+            }
688
+        }
689
+    }
690
+}
691
+
692
+extension _URLEncodedFormEncoder.SingleValueContainer: SingleValueEncodingContainer {
693
+    func encodeNil() throws {
694
+        try checkCanEncode(value: nil)
695
+        defer { canEncodeNewValue = false }
696
+
697
+        let context = EncodingError.Context(codingPath: codingPath,
698
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
699
+        throw EncodingError.invalidValue("nil", context)
700
+    }
701
+
702
+    func encode(_ value: Bool) throws {
703
+        try encode(value, as: String(boolEncoding.encode(value)))
704
+    }
705
+
706
+    func encode(_ value: String) throws {
707
+        try encode(value, as: value)
708
+    }
709
+
710
+    func encode(_ value: Double) throws {
711
+        try encode(value, as: String(value))
712
+    }
713
+
714
+    func encode(_ value: Float) throws {
715
+        try encode(value, as: String(value))
716
+    }
717
+
718
+    func encode(_ value: Int) throws {
719
+        try encode(value, as: String(value))
720
+    }
721
+
722
+    func encode(_ value: Int8) throws {
723
+        try encode(value, as: String(value))
724
+    }
725
+
726
+    func encode(_ value: Int16) throws {
727
+        try encode(value, as: String(value))
728
+    }
729
+
730
+    func encode(_ value: Int32) throws {
731
+        try encode(value, as: String(value))
732
+    }
733
+
734
+    func encode(_ value: Int64) throws {
735
+        try encode(value, as: String(value))
736
+    }
737
+
738
+    func encode(_ value: UInt) throws {
739
+        try encode(value, as: String(value))
740
+    }
741
+
742
+    func encode(_ value: UInt8) throws {
743
+        try encode(value, as: String(value))
744
+    }
745
+
746
+    func encode(_ value: UInt16) throws {
747
+        try encode(value, as: String(value))
748
+    }
749
+
750
+    func encode(_ value: UInt32) throws {
751
+        try encode(value, as: String(value))
752
+    }
753
+
754
+    func encode(_ value: UInt64) throws {
755
+        try encode(value, as: String(value))
756
+    }
757
+
758
+    private func encode<T>(_ value: T, as string: String) throws where T: Encodable {
759
+        try checkCanEncode(value: value)
760
+        defer { canEncodeNewValue = false }
761
+
762
+        context.component.set(to: .string(string), at: codingPath)
763
+    }
764
+
765
+    func encode<T>(_ value: T) throws where T: Encodable {
766
+        switch value {
767
+        case let date as Date:
768
+            guard let string = try dateEncoding.encode(date) else {
769
+                try attemptToEncode(value)
770
+                return
771
+            }
772
+
773
+            try encode(value, as: string)
774
+        case let data as Data:
775
+            guard let string = try dataEncoding.encode(data) else {
776
+                try attemptToEncode(value)
777
+                return
778
+            }
779
+
780
+            try encode(value, as: string)
781
+        default:
782
+            try attemptToEncode(value)
783
+        }
784
+    }
785
+
786
+    private func attemptToEncode<T>(_ value: T) throws where T: Encodable {
787
+        try checkCanEncode(value: value)
788
+        defer { canEncodeNewValue = false }
789
+
790
+        let encoder = _URLEncodedFormEncoder(context: context,
791
+                                             codingPath: codingPath,
792
+                                             boolEncoding: boolEncoding,
793
+                                             dataEncoding: dataEncoding,
794
+                                             dateEncoding: dateEncoding)
795
+        try value.encode(to: encoder)
796
+    }
797
+}
798
+
799
+extension _URLEncodedFormEncoder {
800
+    final class UnkeyedContainer {
801
+        var codingPath: [CodingKey]
802
+
803
+        var count = 0
804
+        var nestedCodingPath: [CodingKey] {
805
+            return codingPath + [AnyCodingKey(intValue: count)!]
806
+        }
807
+
808
+        private let context: URLEncodedFormContext
809
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
810
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
811
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
812
+
813
+        init(context: URLEncodedFormContext,
814
+             codingPath: [CodingKey],
815
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
816
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
817
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
818
+            self.context = context
819
+            self.codingPath = codingPath
820
+            self.boolEncoding = boolEncoding
821
+            self.dataEncoding = dataEncoding
822
+            self.dateEncoding = dateEncoding
823
+        }
824
+    }
825
+}
826
+
827
+extension _URLEncodedFormEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
828
+    func encodeNil() throws {
829
+        let context = EncodingError.Context(codingPath: codingPath,
830
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
831
+        throw EncodingError.invalidValue("nil", context)
832
+    }
833
+
834
+    func encode<T>(_ value: T) throws where T: Encodable {
835
+        var container = nestedSingleValueContainer()
836
+        try container.encode(value)
837
+    }
838
+
839
+    func nestedSingleValueContainer() -> SingleValueEncodingContainer {
840
+        defer { count += 1 }
841
+
842
+        return _URLEncodedFormEncoder.SingleValueContainer(context: context,
843
+                                                           codingPath: nestedCodingPath,
844
+                                                           boolEncoding: boolEncoding,
845
+                                                           dataEncoding: dataEncoding,
846
+                                                           dateEncoding: dateEncoding)
847
+    }
848
+
849
+    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
850
+        defer { count += 1 }
851
+        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,
852
+                                                                         codingPath: nestedCodingPath,
853
+                                                                         boolEncoding: boolEncoding,
854
+                                                                         dataEncoding: dataEncoding,
855
+                                                                         dateEncoding: dateEncoding)
856
+
857
+        return KeyedEncodingContainer(container)
858
+    }
859
+
860
+    func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
861
+        defer { count += 1 }
862
+
863
+        return _URLEncodedFormEncoder.UnkeyedContainer(context: context,
864
+                                                       codingPath: nestedCodingPath,
865
+                                                       boolEncoding: boolEncoding,
866
+                                                       dataEncoding: dataEncoding,
867
+                                                       dateEncoding: dateEncoding)
868
+    }
869
+
870
+    func superEncoder() -> Encoder {
871
+        defer { count += 1 }
872
+
873
+        return _URLEncodedFormEncoder(context: context,
874
+                                      codingPath: codingPath,
875
+                                      boolEncoding: boolEncoding,
876
+                                      dataEncoding: dataEncoding,
877
+                                      dateEncoding: dateEncoding)
878
+    }
879
+}
880
+
881
+final class URLEncodedFormSerializer {
882
+    private let alphabetizeKeyValuePairs: Bool
883
+    private let arrayEncoding: URLEncodedFormEncoder.ArrayEncoding
884
+    private let keyEncoding: URLEncodedFormEncoder.KeyEncoding
885
+    private let spaceEncoding: URLEncodedFormEncoder.SpaceEncoding
886
+    private let allowedCharacters: CharacterSet
887
+
888
+    init(alphabetizeKeyValuePairs: Bool,
889
+         arrayEncoding: URLEncodedFormEncoder.ArrayEncoding,
890
+         keyEncoding: URLEncodedFormEncoder.KeyEncoding,
891
+         spaceEncoding: URLEncodedFormEncoder.SpaceEncoding,
892
+         allowedCharacters: CharacterSet) {
893
+        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs
894
+        self.arrayEncoding = arrayEncoding
895
+        self.keyEncoding = keyEncoding
896
+        self.spaceEncoding = spaceEncoding
897
+        self.allowedCharacters = allowedCharacters
898
+    }
899
+
900
+    func serialize(_ object: URLEncodedFormComponent.Object) -> String {
901
+        var output: [String] = []
902
+        for (key, component) in object {
903
+            let value = serialize(component, forKey: key)
904
+            output.append(value)
905
+        }
906
+        output = alphabetizeKeyValuePairs ? output.sorted() : output
907
+
908
+        return output.joinedWithAmpersands()
909
+    }
910
+
911
+    func serialize(_ component: URLEncodedFormComponent, forKey key: String) -> String {
912
+        switch component {
913
+        case let .string(string): return "\(escape(keyEncoding.encode(key)))=\(escape(string))"
914
+        case let .array(array): return serialize(array, forKey: key)
915
+        case let .object(object): return serialize(object, forKey: key)
916
+        }
917
+    }
918
+
919
+    func serialize(_ object: URLEncodedFormComponent.Object, forKey key: String) -> String {
920
+        var segments: [String] = object.map { subKey, value in
921
+            let keyPath = "[\(subKey)]"
922
+            return serialize(value, forKey: key + keyPath)
923
+        }
924
+        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments
925
+
926
+        return segments.joinedWithAmpersands()
927
+    }
928
+
929
+    func serialize(_ array: [URLEncodedFormComponent], forKey key: String) -> String {
930
+        var segments: [String] = array.map { component in
931
+            let keyPath = arrayEncoding.encode(key)
932
+            return serialize(component, forKey: keyPath)
933
+        }
934
+        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments
935
+
936
+        return segments.joinedWithAmpersands()
937
+    }
938
+
939
+    func escape(_ query: String) -> String {
940
+        var allowedCharactersWithSpace = allowedCharacters
941
+        allowedCharactersWithSpace.insert(charactersIn: " ")
942
+        let escapedQuery = query.addingPercentEncoding(withAllowedCharacters: allowedCharactersWithSpace) ?? query
943
+        let spaceEncodedQuery = spaceEncoding.encode(escapedQuery)
944
+
945
+        return spaceEncodedQuery
946
+    }
947
+}
948
+
949
+extension Array where Element == String {
950
+    func joinedWithAmpersands() -> String {
951
+        return joined(separator: "&")
952
+    }
953
+}
954
+
955
+public extension CharacterSet {
956
+    /// Creates a CharacterSet from RFC 3986 allowed characters.
957
+    ///
958
+    /// RFC 3986 states that the following characters are "reserved" characters.
959
+    ///
960
+    /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
961
+    /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
962
+    ///
963
+    /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
964
+    /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
965
+    /// should be percent-escaped in the query string.
966
+    static let afURLQueryAllowed: CharacterSet = {
967
+        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
968
+        let subDelimitersToEncode = "!$&'()*+,;="
969
+        let encodableDelimiters = CharacterSet(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
970
+
971
+        return CharacterSet.urlQueryAllowed.subtracting(encodableDelimiters)
972
+    }()
973
+}

+ 39
- 0
Pods/Alamofire/Source/URLRequest+Alamofire.swift View File

@@ -0,0 +1,39 @@
1
+//
2
+//  URLRequest+Alamofire.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
+public extension URLRequest {
28
+    /// Returns the `httpMethod` as Alamofire's `HTTPMethod` type.
29
+    var method: HTTPMethod? {
30
+        get { return httpMethod.flatMap(HTTPMethod.init) }
31
+        set { httpMethod = newValue?.rawValue }
32
+    }
33
+
34
+    func validate() throws {
35
+        if method == .get, let bodyData = httpBody {
36
+            throw AFError.urlRequestValidationFailed(reason: .bodyDataInGETRequest(bodyData))
37
+        }
38
+    }
39
+}

+ 37
- 0
Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift View File

@@ -0,0 +1,37 @@
1
+//
2
+//  URLSessionConfiguration+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 Foundation
26
+
27
+extension URLSessionConfiguration: AlamofireExtended {}
28
+extension AlamofireExtension where ExtendedType: URLSessionConfiguration {
29
+    /// Alamofire's default configuration. Same as `URLSessionConfiguration.default` but adds Alamofire default
30
+    /// `Accept-Language`, `Accept-Encoding`, and `User-Agent` headers.
31
+    public static var `default`: URLSessionConfiguration {
32
+        let configuration = URLSessionConfiguration.default
33
+        configuration.headers = .default
34
+
35
+        return configuration
36
+    }
37
+}

+ 247
- 0
Pods/Alamofire/Source/Validation.swift View File

@@ -0,0 +1,247 @@
1
+//
2
+//  Validation.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
+extension Request {
28
+    // MARK: Helper Types
29
+
30
+    fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason
31
+
32
+    /// Used to represent whether a validation succeeded or failed.
33
+    public typealias ValidationResult = Result<Void, Error>
34
+
35
+    fileprivate struct MIMEType {
36
+        let type: String
37
+        let subtype: String
38
+
39
+        var isWildcard: Bool { return type == "*" && subtype == "*" }
40
+
41
+        init?(_ string: String) {
42
+            let components: [String] = {
43
+                let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines)
44
+                let split = stripped[..<(stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)]
45
+
46
+                return split.components(separatedBy: "/")
47
+            }()
48
+
49
+            if let type = components.first, let subtype = components.last {
50
+                self.type = type
51
+                self.subtype = subtype
52
+            } else {
53
+                return nil
54
+            }
55
+        }
56
+
57
+        func matches(_ mime: MIMEType) -> Bool {
58
+            switch (type, subtype) {
59
+            case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"):
60
+                return true
61
+            default:
62
+                return false
63
+            }
64
+        }
65
+    }
66
+
67
+    // MARK: Properties
68
+
69
+    fileprivate var acceptableStatusCodes: Range<Int> { return 200..<300 }
70
+
71
+    fileprivate var acceptableContentTypes: [String] {
72
+        if let accept = request?.value(forHTTPHeaderField: "Accept") {
73
+            return accept.components(separatedBy: ",")
74
+        }
75
+
76
+        return ["*/*"]
77
+    }
78
+
79
+    // MARK: Status Code
80
+
81
+    fileprivate func validate<S: Sequence>(statusCode acceptableStatusCodes: S,
82
+                                           response: HTTPURLResponse)
83
+        -> ValidationResult
84
+        where S.Iterator.Element == Int {
85
+        if acceptableStatusCodes.contains(response.statusCode) {
86
+            return .success(Void())
87
+        } else {
88
+            let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode)
89
+            return .failure(AFError.responseValidationFailed(reason: reason))
90
+        }
91
+    }
92
+
93
+    // MARK: Content Type
94
+
95
+    fileprivate func validate<S: Sequence>(contentType acceptableContentTypes: S,
96
+                                           response: HTTPURLResponse,
97
+                                           data: Data?)
98
+        -> ValidationResult
99
+        where S.Iterator.Element == String {
100
+        guard let data = data, data.count > 0 else { return .success(Void()) }
101
+
102
+        guard
103
+            let responseContentType = response.mimeType,
104
+            let responseMIMEType = MIMEType(responseContentType)
105
+        else {
106
+            for contentType in acceptableContentTypes {
107
+                if let mimeType = MIMEType(contentType), mimeType.isWildcard {
108
+                    return .success(Void())
109
+                }
110
+            }
111
+
112
+            let error: AFError = {
113
+                let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes))
114
+                return AFError.responseValidationFailed(reason: reason)
115
+            }()
116
+
117
+            return .failure(error)
118
+        }
119
+
120
+        for contentType in acceptableContentTypes {
121
+            if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) {
122
+                return .success(Void())
123
+            }
124
+        }
125
+
126
+        let error: AFError = {
127
+            let reason: ErrorReason = .unacceptableContentType(acceptableContentTypes: Array(acceptableContentTypes),
128
+                                                               responseContentType: responseContentType)
129
+
130
+            return AFError.responseValidationFailed(reason: reason)
131
+        }()
132
+
133
+        return .failure(error)
134
+    }
135
+}
136
+
137
+// MARK: -
138
+
139
+extension DataRequest {
140
+    /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the
141
+    /// request was valid.
142
+    public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
143
+
144
+    /// Validates that the response has a status code in the specified sequence.
145
+    ///
146
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
147
+    ///
148
+    /// - parameter range: The range of acceptable status codes.
149
+    ///
150
+    /// - returns: The request.
151
+    @discardableResult
152
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
153
+        return validate { [unowned self] _, response, _ in
154
+            self.validate(statusCode: acceptableStatusCodes, response: response)
155
+        }
156
+    }
157
+
158
+    /// Validates that the response has a content type in the specified sequence.
159
+    ///
160
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
161
+    ///
162
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
163
+    ///
164
+    /// - returns: The request.
165
+    @discardableResult
166
+    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
167
+        return validate { [unowned self] _, response, data in
168
+            self.validate(contentType: acceptableContentTypes(), response: response, data: data)
169
+        }
170
+    }
171
+
172
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
173
+    /// type matches any specified in the Accept HTTP header field.
174
+    ///
175
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
176
+    ///
177
+    /// - returns: The request.
178
+    @discardableResult
179
+    public func validate() -> Self {
180
+        let contentTypes: () -> [String] = { [unowned self] in
181
+            self.acceptableContentTypes
182
+        }
183
+        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
184
+    }
185
+}
186
+
187
+// MARK: -
188
+
189
+extension DownloadRequest {
190
+    /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a
191
+    /// destination URL, and returns whether the request was valid.
192
+    public typealias Validation = (_ request: URLRequest?,
193
+                                   _ response: HTTPURLResponse,
194
+                                   _ fileURL: URL?)
195
+        -> ValidationResult
196
+
197
+    /// Validates that the response has a status code in the specified sequence.
198
+    ///
199
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
200
+    ///
201
+    /// - parameter range: The range of acceptable status codes.
202
+    ///
203
+    /// - returns: The request.
204
+    @discardableResult
205
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
206
+        return validate { [unowned self] _, response, _ in
207
+            self.validate(statusCode: acceptableStatusCodes, response: response)
208
+        }
209
+    }
210
+
211
+    /// Validates that the response has a content type in the specified sequence.
212
+    ///
213
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
214
+    ///
215
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
216
+    ///
217
+    /// - returns: The request.
218
+    @discardableResult
219
+    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
220
+        return validate { [unowned self] _, response, fileURL in
221
+            guard let validFileURL = fileURL else {
222
+                return .failure(AFError.responseValidationFailed(reason: .dataFileNil))
223
+            }
224
+
225
+            do {
226
+                let data = try Data(contentsOf: validFileURL)
227
+                return self.validate(contentType: acceptableContentTypes(), response: response, data: data)
228
+            } catch {
229
+                return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL)))
230
+            }
231
+        }
232
+    }
233
+
234
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
235
+    /// type matches any specified in the Accept HTTP header field.
236
+    ///
237
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
238
+    ///
239
+    /// - returns: The request.
240
+    @discardableResult
241
+    public func validate() -> Self {
242
+        let contentTypes = { [unowned self] in
243
+            self.acceptableContentTypes
244
+        }
245
+        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
246
+    }
247
+}

+ 16
- 0
Pods/Manifest.lock View File

@@ -0,0 +1,16 @@
1
+PODS:
2
+  - Alamofire (5.0.0-rc.3)
3
+
4
+DEPENDENCIES:
5
+  - Alamofire (~> 5.0.0-rc.3)
6
+
7
+SPEC REPOS:
8
+  trunk:
9
+    - Alamofire
10
+
11
+SPEC CHECKSUMS:
12
+  Alamofire: ca8c0de6906873be89d6deec5c8de279e00bf872
13
+
14
+PODFILE CHECKSUM: b48a804833d51d78b77457abd4dc6c8ce3d106a2
15
+
16
+COCOAPODS: 1.8.4

+ 734
- 0
Pods/Pods.xcodeproj/project.pbxproj View File

@@ -0,0 +1,734 @@
1
+// !$*UTF8*$!
2
+{
3
+	archiveVersion = 1;
4
+	classes = {
5
+	};
6
+	objectVersion = 50;
7
+	objects = {
8
+
9
+/* Begin PBXBuildFile section */
10
+		00FA97D56201027AEB1C7692A2C3CF8B /* Alamofire-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8983361440DA703D7E1F9901F2657715 /* Alamofire-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
11
+		0419772A87B16DB7DCF405A9E77D671F /* Protector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1982A99EC0068FB848DB3B942CB83DB5 /* Protector.swift */; };
12
+		06507A26118BA5ACFBBC8C225776920E /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D349810CA61917A72856F3114DE4DA68 /* Validation.swift */; };
13
+		0740575BF9C53FD5B76B51745AB3E71A /* Pods-Trolley App-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C8DAE32FAF9DFD3DE02E5B036BAB4339 /* Pods-Trolley App-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
14
+		0AE06C3AEA6CA45342BA703230ABD2CB /* CachedResponseHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33BB7D85C23DEE0174BE6AFD50EE6E41 /* CachedResponseHandler.swift */; };
15
+		0CC43FF0E31AA320ACFEB0FE6239DF34 /* ServerTrustEvaluation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7059C4CC67DC9BED886103B6F8540E89 /* ServerTrustEvaluation.swift */; };
16
+		13457FE4E607509A3B9527B0711033D5 /* ResponseSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79356BB38DCE3AF0EE679B37B4436ED0 /* ResponseSerialization.swift */; };
17
+		14AB7976E100075ADEA0AB1DB833E72D /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8842C3D78AC0E234008C8E176A413664 /* ParameterEncoding.swift */; };
18
+		17953A9CF2E354B3E69B9ABC2F367AD9 /* AFError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0B912D70323E7F86DCD780B2231C472 /* AFError.swift */; };
19
+		4082513A35C682F2193D002C80F72B79 /* Result+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47152D714F71E858000F62A8A616FCAF /* Result+Alamofire.swift */; };
20
+		42CDB5C986C78BBC8E5C0185F746CABF /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED8657059CCC1AA8B884882B6C21DF3 /* SessionDelegate.swift */; };
21
+		44127C4B989C9CC6A90D78B66A929A5E /* AlamofireExtended.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A6BA50BC9798E96A96694316FD7F19 /* AlamofireExtended.swift */; };
22
+		48D97BE7D5CAED273BD2341C239CC934 /* RequestTaskMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C2ABABCF96583B0736B746A886AECB /* RequestTaskMap.swift */; };
23
+		56EC8ED1535DAB987F3D2B71D4C05773 /* HTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 252E34E06DE82E4A96FF19DDAAB47C48 /* HTTPHeaders.swift */; };
24
+		5C4A0685B5A201436AB52EF25829B333 /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60B0E4FA795EABD32357C1014201A8F9 /* MultipartFormData.swift */; };
25
+		5D12235D061AEE7459279AAF8C348DFE /* URLEncodedFormEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3472833109D10A6D1A67609593B695A /* URLEncodedFormEncoder.swift */; };
26
+		5D61C8ED0DDCC9F8B576B6514B19EE50 /* ParameterEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8926879B94ED50118A3EA9401E92DD /* ParameterEncoder.swift */; };
27
+		69ACE4EEE5A8C1C618B22CC1F7B8EF01 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = F832D5DCB54F4499206CA6D8DECB63DA /* Session.swift */; };
28
+		6A22C46CB1EDE471794D9AB2AC10327F /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6EF2A5FCF56EE72AA71A552A8D39A96 /* Request.swift */; };
29
+		70517C3BAC2D6614347DEAC15299EB84 /* URLConvertible+URLRequestConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93EE927BDAEF08BD7FED7F2C1D56707 /* URLConvertible+URLRequestConvertible.swift */; };
30
+		7CF8362BA31492053F5CB165637AE117 /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC87D7C9C22946B653EC891AD65CA774 /* NetworkReachabilityManager.swift */; };
31
+		8A63EE1D913E6B6D24FADAC01B4A0FA5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */; };
32
+		92811AC5CD9A5004116AE43C4E8FD955 /* OperationQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906744E115B923BC81683FA8522951A8 /* OperationQueue+Alamofire.swift */; };
33
+		97A168DFB6DB61770CE2DBF4FD39AA8D /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B079F294DA5D9A879E6D53A91F51A1E /* CFNetwork.framework */; };
34
+		AD9899986955B2EC1EC20818C860C971 /* RequestInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955C7B41827018BB1B59E447A617F1A6 /* RequestInterceptor.swift */; };
35
+		AF3B5E459910C3162A8DC3DE57044080 /* Pods-Trolley App-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B20936CE73A899AFC85238AF25EADD92 /* Pods-Trolley App-dummy.m */; };
36
+		AF92602937CA016548022C600B8CDC16 /* URLSessionConfiguration+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2598222A405D08F1B87C0463420492F3 /* URLSessionConfiguration+Alamofire.swift */; };
37
+		B1C58F6CED7B3E45170711D9ADF878AF /* Alamofire-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CA569E409E59A3A7C43E582FFFECC049 /* Alamofire-dummy.m */; };
38
+		B23E9A5CDA31534491226F4C2EE8F8E6 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774B0CF83AA71BBED2A70E4A0AE6D9CD /* HTTPMethod.swift */; };
39
+		B788B3354CCEBE56DFDB963CAFD7F6C2 /* Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6818CB68941B73559573DB4F55FF2F /* Alamofire.swift */; };
40
+		BE82AE980F8C7EE28A6448959194F93A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */; };
41
+		C64AF152F7928CDB59385528DB65FE19 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE821E7D82EDB49E8CCB3F4281CB873 /* RedirectHandler.swift */; };
42
+		C7369563F6946D8984124E1A546B6425 /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = A437F36AAA97B99103FBD62EA2687E78 /* Notifications.swift */; };
43
+		CACBD166E573774FB5613C34AA6DA7A7 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76C3EEA63BB9145123705DFCADC8EE27 /* EventMonitor.swift */; };
44
+		D6B2983389480F48F27A0704EEB5DC81 /* RetryPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96ED5BF61D38354434EEDC4FD6779584 /* RetryPolicy.swift */; };
45
+		E07BD425C4EA9ADF15DDFCDB10D0B2FB /* MultipartUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDE34987683B80FE97BBE5736A439B6 /* MultipartUpload.swift */; };
46
+		E4E12208D5246E64B7E6CCAE987ADB03 /* URLRequest+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = D578A4BA4B36B12F7C081E8ED1215837 /* URLRequest+Alamofire.swift */; };
47
+		E9A5AC2F471699CCA516952A5FEB990B /* DispatchQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E408574C32514C9D9055B5A00125B4 /* DispatchQueue+Alamofire.swift */; };
48
+		F71789DC91A75033EFB79DB828676451 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 325AADD7113A629C5C8D34CF07909EFD /* Response.swift */; };
49
+/* End PBXBuildFile section */
50
+
51
+/* Begin PBXContainerItemProxy section */
52
+		FA748911B8BFA28C22FDC216CC82BEF2 /* PBXContainerItemProxy */ = {
53
+			isa = PBXContainerItemProxy;
54
+			containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
55
+			proxyType = 1;
56
+			remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D;
57
+			remoteInfo = Alamofire;
58
+		};
59
+/* End PBXContainerItemProxy section */
60
+
61
+/* Begin PBXFileReference section */
62
+		0F04AFD3B2F75EC4D94DCAAAE6F65E3E /* Pods-Trolley App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Trolley App.debug.xcconfig"; sourceTree = "<group>"; };
63
+		1982A99EC0068FB848DB3B942CB83DB5 /* Protector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Protector.swift; path = Source/Protector.swift; sourceTree = "<group>"; };
64
+		1B1D8193211F4CF8190DD98D24AA5A3C /* Pods-Trolley App-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Trolley App-acknowledgements.markdown"; sourceTree = "<group>"; };
65
+		1C6818CB68941B73559573DB4F55FF2F /* Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Alamofire.swift; path = Source/Alamofire.swift; sourceTree = "<group>"; };
66
+		1F8926879B94ED50118A3EA9401E92DD /* ParameterEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoder.swift; path = Source/ParameterEncoder.swift; sourceTree = "<group>"; };
67
+		222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
68
+		252E34E06DE82E4A96FF19DDAAB47C48 /* HTTPHeaders.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HTTPHeaders.swift; path = Source/HTTPHeaders.swift; sourceTree = "<group>"; };
69
+		2598222A405D08F1B87C0463420492F3 /* URLSessionConfiguration+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URLSessionConfiguration+Alamofire.swift"; path = "Source/URLSessionConfiguration+Alamofire.swift"; sourceTree = "<group>"; };
70
+		325AADD7113A629C5C8D34CF07909EFD /* Response.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Response.swift; path = Source/Response.swift; sourceTree = "<group>"; };
71
+		33BB7D85C23DEE0174BE6AFD50EE6E41 /* CachedResponseHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CachedResponseHandler.swift; path = Source/CachedResponseHandler.swift; sourceTree = "<group>"; };
72
+		393516C6BFFFAB6FC49599474E05B17B /* Pods-Trolley App-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Trolley App-Info.plist"; sourceTree = "<group>"; };
73
+		3A01C48AC23CA9AAC7E0EEF917F07DA5 /* Pods-Trolley App-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Trolley App-acknowledgements.plist"; sourceTree = "<group>"; };
74
+		3CAA211143B95E27EBC3BCF6C0981653 /* Pods-Trolley App.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Trolley App.modulemap"; sourceTree = "<group>"; };
75
+		44309CF1369CA316F5571975E49CC682 /* Pods_Trolley_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Trolley_App.framework; path = "Pods-Trolley App.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
76
+		47152D714F71E858000F62A8A616FCAF /* Result+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Result+Alamofire.swift"; path = "Source/Result+Alamofire.swift"; sourceTree = "<group>"; };
77
+		4F380A974DB08A3A5AAA4F22694A85B3 /* Alamofire.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Alamofire.xcconfig; sourceTree = "<group>"; };
78
+		5C4A2EA954452FABDC9746857D19ED7D /* Alamofire-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Alamofire-Info.plist"; sourceTree = "<group>"; };
79
+		5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Alamofire.framework; path = Alamofire.framework; sourceTree = BUILT_PRODUCTS_DIR; };
80
+		60B0E4FA795EABD32357C1014201A8F9 /* MultipartFormData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartFormData.swift; path = Source/MultipartFormData.swift; sourceTree = "<group>"; };
81
+		6AC6C2A47145FA1261B6E8425F2262E1 /* Alamofire-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-prefix.pch"; sourceTree = "<group>"; };
82
+		7059C4CC67DC9BED886103B6F8540E89 /* ServerTrustEvaluation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServerTrustEvaluation.swift; path = Source/ServerTrustEvaluation.swift; sourceTree = "<group>"; };
83
+		76C3EEA63BB9145123705DFCADC8EE27 /* EventMonitor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EventMonitor.swift; path = Source/EventMonitor.swift; sourceTree = "<group>"; };
84
+		774B0CF83AA71BBED2A70E4A0AE6D9CD /* HTTPMethod.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HTTPMethod.swift; path = Source/HTTPMethod.swift; sourceTree = "<group>"; };
85
+		77E408574C32514C9D9055B5A00125B4 /* DispatchQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+Alamofire.swift"; path = "Source/DispatchQueue+Alamofire.swift"; sourceTree = "<group>"; };
86
+		79356BB38DCE3AF0EE679B37B4436ED0 /* ResponseSerialization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResponseSerialization.swift; path = Source/ResponseSerialization.swift; sourceTree = "<group>"; };
87
+		7A9E60B1A018CCFB58106BB429914737 /* Pods-Trolley App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Trolley App.release.xcconfig"; sourceTree = "<group>"; };
88
+		7BDE34987683B80FE97BBE5736A439B6 /* MultipartUpload.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartUpload.swift; path = Source/MultipartUpload.swift; sourceTree = "<group>"; };
89
+		865132122B5496B9D5D345110ECA8088 /* Pods-Trolley App-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Trolley App-frameworks.sh"; sourceTree = "<group>"; };
90
+		8842C3D78AC0E234008C8E176A413664 /* ParameterEncoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoding.swift; path = Source/ParameterEncoding.swift; sourceTree = "<group>"; };
91
+		8983361440DA703D7E1F9901F2657715 /* Alamofire-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-umbrella.h"; sourceTree = "<group>"; };
92
+		8B079F294DA5D9A879E6D53A91F51A1E /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; };
93
+		906744E115B923BC81683FA8522951A8 /* OperationQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "OperationQueue+Alamofire.swift"; path = "Source/OperationQueue+Alamofire.swift"; sourceTree = "<group>"; };
94
+		955C7B41827018BB1B59E447A617F1A6 /* RequestInterceptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RequestInterceptor.swift; path = Source/RequestInterceptor.swift; sourceTree = "<group>"; };
95
+		96C2ABABCF96583B0736B746A886AECB /* RequestTaskMap.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RequestTaskMap.swift; path = Source/RequestTaskMap.swift; sourceTree = "<group>"; };
96
+		96ED5BF61D38354434EEDC4FD6779584 /* RetryPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RetryPolicy.swift; path = Source/RetryPolicy.swift; sourceTree = "<group>"; };
97
+		9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
98
+		A437F36AAA97B99103FBD62EA2687E78 /* Notifications.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Notifications.swift; path = Source/Notifications.swift; sourceTree = "<group>"; };
99
+		A6EF2A5FCF56EE72AA71A552A8D39A96 /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Request.swift; path = Source/Request.swift; sourceTree = "<group>"; };
100
+		A93EE927BDAEF08BD7FED7F2C1D56707 /* URLConvertible+URLRequestConvertible.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URLConvertible+URLRequestConvertible.swift"; path = "Source/URLConvertible+URLRequestConvertible.swift"; sourceTree = "<group>"; };
101
+		B0B912D70323E7F86DCD780B2231C472 /* AFError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AFError.swift; path = Source/AFError.swift; sourceTree = "<group>"; };
102
+		B20936CE73A899AFC85238AF25EADD92 /* Pods-Trolley App-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Trolley App-dummy.m"; sourceTree = "<group>"; };
103
+		C8DAE32FAF9DFD3DE02E5B036BAB4339 /* Pods-Trolley App-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Trolley App-umbrella.h"; sourceTree = "<group>"; };
104
+		CA569E409E59A3A7C43E582FFFECC049 /* Alamofire-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Alamofire-dummy.m"; sourceTree = "<group>"; };
105
+		CDE821E7D82EDB49E8CCB3F4281CB873 /* RedirectHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RedirectHandler.swift; path = Source/RedirectHandler.swift; sourceTree = "<group>"; };
106
+		D1A6BA50BC9798E96A96694316FD7F19 /* AlamofireExtended.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlamofireExtended.swift; path = Source/AlamofireExtended.swift; sourceTree = "<group>"; };
107
+		D2D875F7C044C8B217EF5F195FE38EF6 /* Alamofire.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Alamofire.modulemap; sourceTree = "<group>"; };
108
+		D3472833109D10A6D1A67609593B695A /* URLEncodedFormEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLEncodedFormEncoder.swift; path = Source/URLEncodedFormEncoder.swift; sourceTree = "<group>"; };
109
+		D349810CA61917A72856F3114DE4DA68 /* Validation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Validation.swift; path = Source/Validation.swift; sourceTree = "<group>"; };
110
+		D578A4BA4B36B12F7C081E8ED1215837 /* URLRequest+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URLRequest+Alamofire.swift"; path = "Source/URLRequest+Alamofire.swift"; sourceTree = "<group>"; };
111
+		F832D5DCB54F4499206CA6D8DECB63DA /* Session.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Session.swift; path = Source/Session.swift; sourceTree = "<group>"; };
112
+		FC87D7C9C22946B653EC891AD65CA774 /* NetworkReachabilityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkReachabilityManager.swift; path = Source/NetworkReachabilityManager.swift; sourceTree = "<group>"; };
113
+		FED8657059CCC1AA8B884882B6C21DF3 /* SessionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDelegate.swift; path = Source/SessionDelegate.swift; sourceTree = "<group>"; };
114
+/* End PBXFileReference section */
115
+
116
+/* Begin PBXFrameworksBuildPhase section */
117
+		8B0D8633F410345F93419B8C3D7B6916 /* Frameworks */ = {
118
+			isa = PBXFrameworksBuildPhase;
119
+			buildActionMask = 2147483647;
120
+			files = (
121
+				97A168DFB6DB61770CE2DBF4FD39AA8D /* CFNetwork.framework in Frameworks */,
122
+				BE82AE980F8C7EE28A6448959194F93A /* Foundation.framework in Frameworks */,
123
+			);
124
+			runOnlyForDeploymentPostprocessing = 0;
125
+		};
126
+		FD8B7DC19AAC44AC3AFDD0041DB2B4AC /* Frameworks */ = {
127
+			isa = PBXFrameworksBuildPhase;
128
+			buildActionMask = 2147483647;
129
+			files = (
130
+				8A63EE1D913E6B6D24FADAC01B4A0FA5 /* Foundation.framework in Frameworks */,
131
+			);
132
+			runOnlyForDeploymentPostprocessing = 0;
133
+		};
134
+/* End PBXFrameworksBuildPhase section */
135
+
136
+/* Begin PBXGroup section */
137
+		08C3CADBFE7473C8C2720B971358481C /* Pods */ = {
138
+			isa = PBXGroup;
139
+			children = (
140
+				CC1ED248BA98F2E22521DA618B8E5953 /* Alamofire */,
141
+			);
142
+			name = Pods;
143
+			sourceTree = "<group>";
144
+		};
145
+		1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = {
146
+			isa = PBXGroup;
147
+			children = (
148
+				E34DCC8E2CF86B8D72232914781A840D /* iOS */,
149
+			);
150
+			name = Frameworks;
151
+			sourceTree = "<group>";
152
+		};
153
+		1713D5D26513A71876A7F5676C179011 /* Targets Support Files */ = {
154
+			isa = PBXGroup;
155
+			children = (
156
+				652971AEECA6C4C8D08F6C665FA2E63F /* Pods-Trolley App */,
157
+			);
158
+			name = "Targets Support Files";
159
+			sourceTree = "<group>";
160
+		};
161
+		652971AEECA6C4C8D08F6C665FA2E63F /* Pods-Trolley App */ = {
162
+			isa = PBXGroup;
163
+			children = (
164
+				3CAA211143B95E27EBC3BCF6C0981653 /* Pods-Trolley App.modulemap */,
165
+				1B1D8193211F4CF8190DD98D24AA5A3C /* Pods-Trolley App-acknowledgements.markdown */,
166
+				3A01C48AC23CA9AAC7E0EEF917F07DA5 /* Pods-Trolley App-acknowledgements.plist */,
167
+				B20936CE73A899AFC85238AF25EADD92 /* Pods-Trolley App-dummy.m */,
168
+				865132122B5496B9D5D345110ECA8088 /* Pods-Trolley App-frameworks.sh */,
169
+				393516C6BFFFAB6FC49599474E05B17B /* Pods-Trolley App-Info.plist */,
170
+				C8DAE32FAF9DFD3DE02E5B036BAB4339 /* Pods-Trolley App-umbrella.h */,
171
+				0F04AFD3B2F75EC4D94DCAAAE6F65E3E /* Pods-Trolley App.debug.xcconfig */,
172
+				7A9E60B1A018CCFB58106BB429914737 /* Pods-Trolley App.release.xcconfig */,
173
+			);
174
+			name = "Pods-Trolley App";
175
+			path = "Target Support Files/Pods-Trolley App";
176
+			sourceTree = "<group>";
177
+		};
178
+		ABC245D95E0876344B1070948D191E18 /* Products */ = {
179
+			isa = PBXGroup;
180
+			children = (
181
+				5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */,
182
+				44309CF1369CA316F5571975E49CC682 /* Pods_Trolley_App.framework */,
183
+			);
184
+			name = Products;
185
+			sourceTree = "<group>";
186
+		};
187
+		CC1ED248BA98F2E22521DA618B8E5953 /* Alamofire */ = {
188
+			isa = PBXGroup;
189
+			children = (
190
+				B0B912D70323E7F86DCD780B2231C472 /* AFError.swift */,
191
+				1C6818CB68941B73559573DB4F55FF2F /* Alamofire.swift */,
192
+				D1A6BA50BC9798E96A96694316FD7F19 /* AlamofireExtended.swift */,
193
+				33BB7D85C23DEE0174BE6AFD50EE6E41 /* CachedResponseHandler.swift */,
194
+				77E408574C32514C9D9055B5A00125B4 /* DispatchQueue+Alamofire.swift */,
195
+				76C3EEA63BB9145123705DFCADC8EE27 /* EventMonitor.swift */,
196
+				252E34E06DE82E4A96FF19DDAAB47C48 /* HTTPHeaders.swift */,
197
+				774B0CF83AA71BBED2A70E4A0AE6D9CD /* HTTPMethod.swift */,
198
+				60B0E4FA795EABD32357C1014201A8F9 /* MultipartFormData.swift */,
199
+				7BDE34987683B80FE97BBE5736A439B6 /* MultipartUpload.swift */,
200
+				FC87D7C9C22946B653EC891AD65CA774 /* NetworkReachabilityManager.swift */,
201
+				A437F36AAA97B99103FBD62EA2687E78 /* Notifications.swift */,
202
+				906744E115B923BC81683FA8522951A8 /* OperationQueue+Alamofire.swift */,
203
+				1F8926879B94ED50118A3EA9401E92DD /* ParameterEncoder.swift */,
204
+				8842C3D78AC0E234008C8E176A413664 /* ParameterEncoding.swift */,
205
+				1982A99EC0068FB848DB3B942CB83DB5 /* Protector.swift */,
206
+				CDE821E7D82EDB49E8CCB3F4281CB873 /* RedirectHandler.swift */,
207
+				A6EF2A5FCF56EE72AA71A552A8D39A96 /* Request.swift */,
208
+				955C7B41827018BB1B59E447A617F1A6 /* RequestInterceptor.swift */,
209
+				96C2ABABCF96583B0736B746A886AECB /* RequestTaskMap.swift */,
210
+				325AADD7113A629C5C8D34CF07909EFD /* Response.swift */,
211
+				79356BB38DCE3AF0EE679B37B4436ED0 /* ResponseSerialization.swift */,
212
+				47152D714F71E858000F62A8A616FCAF /* Result+Alamofire.swift */,
213
+				96ED5BF61D38354434EEDC4FD6779584 /* RetryPolicy.swift */,
214
+				7059C4CC67DC9BED886103B6F8540E89 /* ServerTrustEvaluation.swift */,
215
+				F832D5DCB54F4499206CA6D8DECB63DA /* Session.swift */,
216
+				FED8657059CCC1AA8B884882B6C21DF3 /* SessionDelegate.swift */,
217
+				A93EE927BDAEF08BD7FED7F2C1D56707 /* URLConvertible+URLRequestConvertible.swift */,
218
+				D3472833109D10A6D1A67609593B695A /* URLEncodedFormEncoder.swift */,
219
+				D578A4BA4B36B12F7C081E8ED1215837 /* URLRequest+Alamofire.swift */,
220
+				2598222A405D08F1B87C0463420492F3 /* URLSessionConfiguration+Alamofire.swift */,
221
+				D349810CA61917A72856F3114DE4DA68 /* Validation.swift */,
222
+				E54E43FD3458F5DE8FE802AE2526AF81 /* Support Files */,
223
+			);
224
+			name = Alamofire;
225
+			path = Alamofire;
226
+			sourceTree = "<group>";
227
+		};
228
+		CF1408CF629C7361332E53B88F7BD30C = {
229
+			isa = PBXGroup;
230
+			children = (
231
+				9D940727FF8FB9C785EB98E56350EF41 /* Podfile */,
232
+				1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */,
233
+				08C3CADBFE7473C8C2720B971358481C /* Pods */,
234
+				ABC245D95E0876344B1070948D191E18 /* Products */,
235
+				1713D5D26513A71876A7F5676C179011 /* Targets Support Files */,
236
+			);
237
+			sourceTree = "<group>";
238
+		};
239
+		E34DCC8E2CF86B8D72232914781A840D /* iOS */ = {
240
+			isa = PBXGroup;
241
+			children = (
242
+				8B079F294DA5D9A879E6D53A91F51A1E /* CFNetwork.framework */,
243
+				222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */,
244
+			);
245
+			name = iOS;
246
+			sourceTree = "<group>";
247
+		};
248
+		E54E43FD3458F5DE8FE802AE2526AF81 /* Support Files */ = {
249
+			isa = PBXGroup;
250
+			children = (
251
+				D2D875F7C044C8B217EF5F195FE38EF6 /* Alamofire.modulemap */,
252
+				4F380A974DB08A3A5AAA4F22694A85B3 /* Alamofire.xcconfig */,
253
+				CA569E409E59A3A7C43E582FFFECC049 /* Alamofire-dummy.m */,
254
+				5C4A2EA954452FABDC9746857D19ED7D /* Alamofire-Info.plist */,
255
+				6AC6C2A47145FA1261B6E8425F2262E1 /* Alamofire-prefix.pch */,
256
+				8983361440DA703D7E1F9901F2657715 /* Alamofire-umbrella.h */,
257
+			);
258
+			name = "Support Files";
259
+			path = "../Target Support Files/Alamofire";
260
+			sourceTree = "<group>";
261
+		};
262
+/* End PBXGroup section */
263
+
264
+/* Begin PBXHeadersBuildPhase section */
265
+		ADDF288DD930A46B5F0F198C225895C9 /* Headers */ = {
266
+			isa = PBXHeadersBuildPhase;
267
+			buildActionMask = 2147483647;
268
+			files = (
269
+				00FA97D56201027AEB1C7692A2C3CF8B /* Alamofire-umbrella.h in Headers */,
270
+			);
271
+			runOnlyForDeploymentPostprocessing = 0;
272
+		};
273
+		F49E47658F9D06A7E9D2755AC1956B17 /* Headers */ = {
274
+			isa = PBXHeadersBuildPhase;
275
+			buildActionMask = 2147483647;
276
+			files = (
277
+				0740575BF9C53FD5B76B51745AB3E71A /* Pods-Trolley App-umbrella.h in Headers */,
278
+			);
279
+			runOnlyForDeploymentPostprocessing = 0;
280
+		};
281
+/* End PBXHeadersBuildPhase section */
282
+
283
+/* Begin PBXNativeTarget section */
284
+		171A0B9EEB8AE346EB29A7957BE4577E /* Pods-Trolley App */ = {
285
+			isa = PBXNativeTarget;
286
+			buildConfigurationList = 8A892D142004BAC5BDD0C2341E6D452F /* Build configuration list for PBXNativeTarget "Pods-Trolley App" */;
287
+			buildPhases = (
288
+				F49E47658F9D06A7E9D2755AC1956B17 /* Headers */,
289
+				67B04D2B1B6D7FF49861CBE04C71CFF9 /* Sources */,
290
+				FD8B7DC19AAC44AC3AFDD0041DB2B4AC /* Frameworks */,
291
+				A583A925C8146F72976E3DC3D0F51ED4 /* Resources */,
292
+			);
293
+			buildRules = (
294
+			);
295
+			dependencies = (
296
+				E23D53ADF3FCB1DCE5D12B3B248D70E4 /* PBXTargetDependency */,
297
+			);
298
+			name = "Pods-Trolley App";
299
+			productName = "Pods-Trolley App";
300
+			productReference = 44309CF1369CA316F5571975E49CC682 /* Pods_Trolley_App.framework */;
301
+			productType = "com.apple.product-type.framework";
302
+		};
303
+		EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */ = {
304
+			isa = PBXNativeTarget;
305
+			buildConfigurationList = 6B2B8EC7E21CDBFF2BDA26B1B4AC4C0D /* Build configuration list for PBXNativeTarget "Alamofire" */;
306
+			buildPhases = (
307
+				ADDF288DD930A46B5F0F198C225895C9 /* Headers */,
308
+				7349DB0E9BEBE664696F1DCC25226F26 /* Sources */,
309
+				8B0D8633F410345F93419B8C3D7B6916 /* Frameworks */,
310
+				28FC0024B79C28A420D7C4FEBB9E3AEB /* Resources */,
311
+			);
312
+			buildRules = (
313
+			);
314
+			dependencies = (
315
+			);
316
+			name = Alamofire;
317
+			productName = Alamofire;
318
+			productReference = 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */;
319
+			productType = "com.apple.product-type.framework";
320
+		};
321
+/* End PBXNativeTarget section */
322
+
323
+/* Begin PBXProject section */
324
+		BFDFE7DC352907FC980B868725387E98 /* Project object */ = {
325
+			isa = PBXProject;
326
+			attributes = {
327
+				LastSwiftUpdateCheck = 1100;
328
+				LastUpgradeCheck = 1100;
329
+			};
330
+			buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */;
331
+			compatibilityVersion = "Xcode 9.3";
332
+			developmentRegion = en;
333
+			hasScannedForEncodings = 0;
334
+			knownRegions = (
335
+				en,
336
+				Base,
337
+			);
338
+			mainGroup = CF1408CF629C7361332E53B88F7BD30C;
339
+			productRefGroup = ABC245D95E0876344B1070948D191E18 /* Products */;
340
+			projectDirPath = "";
341
+			projectRoot = "";
342
+			targets = (
343
+				EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */,
344
+				171A0B9EEB8AE346EB29A7957BE4577E /* Pods-Trolley App */,
345
+			);
346
+		};
347
+/* End PBXProject section */
348
+
349
+/* Begin PBXResourcesBuildPhase section */
350
+		28FC0024B79C28A420D7C4FEBB9E3AEB /* Resources */ = {
351
+			isa = PBXResourcesBuildPhase;
352
+			buildActionMask = 2147483647;
353
+			files = (
354
+			);
355
+			runOnlyForDeploymentPostprocessing = 0;
356
+		};
357
+		A583A925C8146F72976E3DC3D0F51ED4 /* Resources */ = {
358
+			isa = PBXResourcesBuildPhase;
359
+			buildActionMask = 2147483647;
360
+			files = (
361
+			);
362
+			runOnlyForDeploymentPostprocessing = 0;
363
+		};
364
+/* End PBXResourcesBuildPhase section */
365
+
366
+/* Begin PBXSourcesBuildPhase section */
367
+		67B04D2B1B6D7FF49861CBE04C71CFF9 /* Sources */ = {
368
+			isa = PBXSourcesBuildPhase;
369
+			buildActionMask = 2147483647;
370
+			files = (
371
+				AF3B5E459910C3162A8DC3DE57044080 /* Pods-Trolley App-dummy.m in Sources */,
372
+			);
373
+			runOnlyForDeploymentPostprocessing = 0;
374
+		};
375
+		7349DB0E9BEBE664696F1DCC25226F26 /* Sources */ = {
376
+			isa = PBXSourcesBuildPhase;
377
+			buildActionMask = 2147483647;
378
+			files = (
379
+				17953A9CF2E354B3E69B9ABC2F367AD9 /* AFError.swift in Sources */,
380
+				B1C58F6CED7B3E45170711D9ADF878AF /* Alamofire-dummy.m in Sources */,
381
+				B788B3354CCEBE56DFDB963CAFD7F6C2 /* Alamofire.swift in Sources */,
382
+				44127C4B989C9CC6A90D78B66A929A5E /* AlamofireExtended.swift in Sources */,
383
+				0AE06C3AEA6CA45342BA703230ABD2CB /* CachedResponseHandler.swift in Sources */,
384
+				E9A5AC2F471699CCA516952A5FEB990B /* DispatchQueue+Alamofire.swift in Sources */,
385
+				CACBD166E573774FB5613C34AA6DA7A7 /* EventMonitor.swift in Sources */,
386
+				56EC8ED1535DAB987F3D2B71D4C05773 /* HTTPHeaders.swift in Sources */,
387
+				B23E9A5CDA31534491226F4C2EE8F8E6 /* HTTPMethod.swift in Sources */,
388
+				5C4A0685B5A201436AB52EF25829B333 /* MultipartFormData.swift in Sources */,
389
+				E07BD425C4EA9ADF15DDFCDB10D0B2FB /* MultipartUpload.swift in Sources */,
390
+				7CF8362BA31492053F5CB165637AE117 /* NetworkReachabilityManager.swift in Sources */,
391
+				C7369563F6946D8984124E1A546B6425 /* Notifications.swift in Sources */,
392
+				92811AC5CD9A5004116AE43C4E8FD955 /* OperationQueue+Alamofire.swift in Sources */,
393
+				5D61C8ED0DDCC9F8B576B6514B19EE50 /* ParameterEncoder.swift in Sources */,
394
+				14AB7976E100075ADEA0AB1DB833E72D /* ParameterEncoding.swift in Sources */,
395
+				0419772A87B16DB7DCF405A9E77D671F /* Protector.swift in Sources */,
396
+				C64AF152F7928CDB59385528DB65FE19 /* RedirectHandler.swift in Sources */,
397
+				6A22C46CB1EDE471794D9AB2AC10327F /* Request.swift in Sources */,
398
+				AD9899986955B2EC1EC20818C860C971 /* RequestInterceptor.swift in Sources */,
399
+				48D97BE7D5CAED273BD2341C239CC934 /* RequestTaskMap.swift in Sources */,
400
+				F71789DC91A75033EFB79DB828676451 /* Response.swift in Sources */,
401
+				13457FE4E607509A3B9527B0711033D5 /* ResponseSerialization.swift in Sources */,
402
+				4082513A35C682F2193D002C80F72B79 /* Result+Alamofire.swift in Sources */,
403
+				D6B2983389480F48F27A0704EEB5DC81 /* RetryPolicy.swift in Sources */,
404
+				0CC43FF0E31AA320ACFEB0FE6239DF34 /* ServerTrustEvaluation.swift in Sources */,
405
+				69ACE4EEE5A8C1C618B22CC1F7B8EF01 /* Session.swift in Sources */,
406
+				42CDB5C986C78BBC8E5C0185F746CABF /* SessionDelegate.swift in Sources */,
407
+				70517C3BAC2D6614347DEAC15299EB84 /* URLConvertible+URLRequestConvertible.swift in Sources */,
408
+				5D12235D061AEE7459279AAF8C348DFE /* URLEncodedFormEncoder.swift in Sources */,
409
+				E4E12208D5246E64B7E6CCAE987ADB03 /* URLRequest+Alamofire.swift in Sources */,
410
+				AF92602937CA016548022C600B8CDC16 /* URLSessionConfiguration+Alamofire.swift in Sources */,
411
+				06507A26118BA5ACFBBC8C225776920E /* Validation.swift in Sources */,
412
+			);
413
+			runOnlyForDeploymentPostprocessing = 0;
414
+		};
415
+/* End PBXSourcesBuildPhase section */
416
+
417
+/* Begin PBXTargetDependency section */
418
+		E23D53ADF3FCB1DCE5D12B3B248D70E4 /* PBXTargetDependency */ = {
419
+			isa = PBXTargetDependency;
420
+			name = Alamofire;
421
+			target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */;
422
+			targetProxy = FA748911B8BFA28C22FDC216CC82BEF2 /* PBXContainerItemProxy */;
423
+		};
424
+/* End PBXTargetDependency section */
425
+
426
+/* Begin XCBuildConfiguration section */
427
+		00319A2330DC739FCBFBB6CFB0C5F58D /* Debug */ = {
428
+			isa = XCBuildConfiguration;
429
+			baseConfigurationReference = 4F380A974DB08A3A5AAA4F22694A85B3 /* Alamofire.xcconfig */;
430
+			buildSettings = {
431
+				CLANG_ENABLE_OBJC_WEAK = NO;
432
+				CODE_SIGN_IDENTITY = "";
433
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
434
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
435
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
436
+				CURRENT_PROJECT_VERSION = 1;
437
+				DEFINES_MODULE = YES;
438
+				DYLIB_COMPATIBILITY_VERSION = 1;
439
+				DYLIB_CURRENT_VERSION = 1;
440
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
441
+				GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch";
442
+				INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist";
443
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
444
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
445
+				LD_RUNPATH_SEARCH_PATHS = (
446
+					"$(inherited)",
447
+					"@executable_path/Frameworks",
448
+					"@loader_path/Frameworks",
449
+				);
450
+				MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap";
451
+				PRODUCT_MODULE_NAME = Alamofire;
452
+				PRODUCT_NAME = Alamofire;
453
+				SDKROOT = iphoneos;
454
+				SKIP_INSTALL = YES;
455
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) ";
456
+				SWIFT_VERSION = 5.1;
457
+				TARGETED_DEVICE_FAMILY = "1,2";
458
+				VERSIONING_SYSTEM = "apple-generic";
459
+				VERSION_INFO_PREFIX = "";
460
+			};
461
+			name = Debug;
462
+		};
463
+		510B057D2E9F059C50D52DA5D90F3ACF /* Release */ = {
464
+			isa = XCBuildConfiguration;
465
+			buildSettings = {
466
+				ALWAYS_SEARCH_USER_PATHS = NO;
467
+				CLANG_ANALYZER_NONNULL = YES;
468
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
469
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
470
+				CLANG_CXX_LIBRARY = "libc++";
471
+				CLANG_ENABLE_MODULES = YES;
472
+				CLANG_ENABLE_OBJC_ARC = YES;
473
+				CLANG_ENABLE_OBJC_WEAK = YES;
474
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
475
+				CLANG_WARN_BOOL_CONVERSION = YES;
476
+				CLANG_WARN_COMMA = YES;
477
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
478
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
479
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
480
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
481
+				CLANG_WARN_EMPTY_BODY = YES;
482
+				CLANG_WARN_ENUM_CONVERSION = YES;
483
+				CLANG_WARN_INFINITE_RECURSION = YES;
484
+				CLANG_WARN_INT_CONVERSION = YES;
485
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
486
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
487
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
488
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
489
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
490
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
491
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
492
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
493
+				CLANG_WARN_UNREACHABLE_CODE = YES;
494
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
495
+				COPY_PHASE_STRIP = NO;
496
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
497
+				ENABLE_NS_ASSERTIONS = NO;
498
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
499
+				GCC_C_LANGUAGE_STANDARD = gnu11;
500
+				GCC_NO_COMMON_BLOCKS = YES;
501
+				GCC_PREPROCESSOR_DEFINITIONS = (
502
+					"POD_CONFIGURATION_RELEASE=1",
503
+					"$(inherited)",
504
+				);
505
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
506
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
507
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
508
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
509
+				GCC_WARN_UNUSED_FUNCTION = YES;
510
+				GCC_WARN_UNUSED_VARIABLE = YES;
511
+				IPHONEOS_DEPLOYMENT_TARGET = 13.1;
512
+				MTL_ENABLE_DEBUG_INFO = NO;
513
+				MTL_FAST_MATH = YES;
514
+				PRODUCT_NAME = "$(TARGET_NAME)";
515
+				STRIP_INSTALLED_PRODUCT = NO;
516
+				SWIFT_COMPILATION_MODE = wholemodule;
517
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
518
+				SWIFT_VERSION = 5.0;
519
+				SYMROOT = "${SRCROOT}/../build";
520
+			};
521
+			name = Release;
522
+		};
523
+		73367964D542BFDEE266363279883884 /* Debug */ = {
524
+			isa = XCBuildConfiguration;
525
+			baseConfigurationReference = 0F04AFD3B2F75EC4D94DCAAAE6F65E3E /* Pods-Trolley App.debug.xcconfig */;
526
+			buildSettings = {
527
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
528
+				CLANG_ENABLE_OBJC_WEAK = NO;
529
+				CODE_SIGN_IDENTITY = "";
530
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
531
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
532
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
533
+				CURRENT_PROJECT_VERSION = 1;
534
+				DEFINES_MODULE = YES;
535
+				DYLIB_COMPATIBILITY_VERSION = 1;
536
+				DYLIB_CURRENT_VERSION = 1;
537
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
538
+				INFOPLIST_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist";
539
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
540
+				IPHONEOS_DEPLOYMENT_TARGET = 13.1;
541
+				LD_RUNPATH_SEARCH_PATHS = (
542
+					"$(inherited)",
543
+					"@executable_path/Frameworks",
544
+					"@loader_path/Frameworks",
545
+				);
546
+				MACH_O_TYPE = staticlib;
547
+				MODULEMAP_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap";
548
+				OTHER_LDFLAGS = "";
549
+				OTHER_LIBTOOLFLAGS = "";
550
+				PODS_ROOT = "$(SRCROOT)";
551
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
552
+				PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
553
+				SDKROOT = iphoneos;
554
+				SKIP_INSTALL = YES;
555
+				TARGETED_DEVICE_FAMILY = "1,2";
556
+				VERSIONING_SYSTEM = "apple-generic";
557
+				VERSION_INFO_PREFIX = "";
558
+			};
559
+			name = Debug;
560
+		};
561
+		804E13245C9FBBE6A340C555CA8B2B4C /* Debug */ = {
562
+			isa = XCBuildConfiguration;
563
+			buildSettings = {
564
+				ALWAYS_SEARCH_USER_PATHS = NO;
565
+				CLANG_ANALYZER_NONNULL = YES;
566
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
567
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
568
+				CLANG_CXX_LIBRARY = "libc++";
569
+				CLANG_ENABLE_MODULES = YES;
570
+				CLANG_ENABLE_OBJC_ARC = YES;
571
+				CLANG_ENABLE_OBJC_WEAK = YES;
572
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
573
+				CLANG_WARN_BOOL_CONVERSION = YES;
574
+				CLANG_WARN_COMMA = YES;
575
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
576
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
577
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
578
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
579
+				CLANG_WARN_EMPTY_BODY = YES;
580
+				CLANG_WARN_ENUM_CONVERSION = YES;
581
+				CLANG_WARN_INFINITE_RECURSION = YES;
582
+				CLANG_WARN_INT_CONVERSION = YES;
583
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
584
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
585
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
586
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
587
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
588
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
589
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
590
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
591
+				CLANG_WARN_UNREACHABLE_CODE = YES;
592
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
593
+				COPY_PHASE_STRIP = NO;
594
+				DEBUG_INFORMATION_FORMAT = dwarf;
595
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
596
+				ENABLE_TESTABILITY = YES;
597
+				GCC_C_LANGUAGE_STANDARD = gnu11;
598
+				GCC_DYNAMIC_NO_PIC = NO;
599
+				GCC_NO_COMMON_BLOCKS = YES;
600
+				GCC_OPTIMIZATION_LEVEL = 0;
601
+				GCC_PREPROCESSOR_DEFINITIONS = (
602
+					"POD_CONFIGURATION_DEBUG=1",
603
+					"DEBUG=1",
604
+					"$(inherited)",
605
+				);
606
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
607
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
608
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
609
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
610
+				GCC_WARN_UNUSED_FUNCTION = YES;
611
+				GCC_WARN_UNUSED_VARIABLE = YES;
612
+				IPHONEOS_DEPLOYMENT_TARGET = 13.1;
613
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
614
+				MTL_FAST_MATH = YES;
615
+				ONLY_ACTIVE_ARCH = YES;
616
+				PRODUCT_NAME = "$(TARGET_NAME)";
617
+				STRIP_INSTALLED_PRODUCT = NO;
618
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
619
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
620
+				SWIFT_VERSION = 5.0;
621
+				SYMROOT = "${SRCROOT}/../build";
622
+			};
623
+			name = Debug;
624
+		};
625
+		ADED795A3A5F72281E91FB612D07F320 /* Release */ = {
626
+			isa = XCBuildConfiguration;
627
+			baseConfigurationReference = 7A9E60B1A018CCFB58106BB429914737 /* Pods-Trolley App.release.xcconfig */;
628
+			buildSettings = {
629
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
630
+				CLANG_ENABLE_OBJC_WEAK = NO;
631
+				CODE_SIGN_IDENTITY = "";
632
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
633
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
634
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
635
+				CURRENT_PROJECT_VERSION = 1;
636
+				DEFINES_MODULE = YES;
637
+				DYLIB_COMPATIBILITY_VERSION = 1;
638
+				DYLIB_CURRENT_VERSION = 1;
639
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
640
+				INFOPLIST_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist";
641
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
642
+				IPHONEOS_DEPLOYMENT_TARGET = 13.1;
643
+				LD_RUNPATH_SEARCH_PATHS = (
644
+					"$(inherited)",
645
+					"@executable_path/Frameworks",
646
+					"@loader_path/Frameworks",
647
+				);
648
+				MACH_O_TYPE = staticlib;
649
+				MODULEMAP_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap";
650
+				OTHER_LDFLAGS = "";
651
+				OTHER_LIBTOOLFLAGS = "";
652
+				PODS_ROOT = "$(SRCROOT)";
653
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
654
+				PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
655
+				SDKROOT = iphoneos;
656
+				SKIP_INSTALL = YES;
657
+				TARGETED_DEVICE_FAMILY = "1,2";
658
+				VALIDATE_PRODUCT = YES;
659
+				VERSIONING_SYSTEM = "apple-generic";
660
+				VERSION_INFO_PREFIX = "";
661
+			};
662
+			name = Release;
663
+		};
664
+		F659822BFF3B3C20B29B76B89800A5E9 /* Release */ = {
665
+			isa = XCBuildConfiguration;
666
+			baseConfigurationReference = 4F380A974DB08A3A5AAA4F22694A85B3 /* Alamofire.xcconfig */;
667
+			buildSettings = {
668
+				CLANG_ENABLE_OBJC_WEAK = NO;
669
+				CODE_SIGN_IDENTITY = "";
670
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
671
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
672
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
673
+				CURRENT_PROJECT_VERSION = 1;
674
+				DEFINES_MODULE = YES;
675
+				DYLIB_COMPATIBILITY_VERSION = 1;
676
+				DYLIB_CURRENT_VERSION = 1;
677
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
678
+				GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch";
679
+				INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist";
680
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
681
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
682
+				LD_RUNPATH_SEARCH_PATHS = (
683
+					"$(inherited)",
684
+					"@executable_path/Frameworks",
685
+					"@loader_path/Frameworks",
686
+				);
687
+				MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap";
688
+				PRODUCT_MODULE_NAME = Alamofire;
689
+				PRODUCT_NAME = Alamofire;
690
+				SDKROOT = iphoneos;
691
+				SKIP_INSTALL = YES;
692
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) ";
693
+				SWIFT_VERSION = 5.1;
694
+				TARGETED_DEVICE_FAMILY = "1,2";
695
+				VALIDATE_PRODUCT = YES;
696
+				VERSIONING_SYSTEM = "apple-generic";
697
+				VERSION_INFO_PREFIX = "";
698
+			};
699
+			name = Release;
700
+		};
701
+/* End XCBuildConfiguration section */
702
+
703
+/* Begin XCConfigurationList section */
704
+		4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = {
705
+			isa = XCConfigurationList;
706
+			buildConfigurations = (
707
+				804E13245C9FBBE6A340C555CA8B2B4C /* Debug */,
708
+				510B057D2E9F059C50D52DA5D90F3ACF /* Release */,
709
+			);
710
+			defaultConfigurationIsVisible = 0;
711
+			defaultConfigurationName = Release;
712
+		};
713
+		6B2B8EC7E21CDBFF2BDA26B1B4AC4C0D /* Build configuration list for PBXNativeTarget "Alamofire" */ = {
714
+			isa = XCConfigurationList;
715
+			buildConfigurations = (
716
+				00319A2330DC739FCBFBB6CFB0C5F58D /* Debug */,
717
+				F659822BFF3B3C20B29B76B89800A5E9 /* Release */,
718
+			);
719
+			defaultConfigurationIsVisible = 0;
720
+			defaultConfigurationName = Release;
721
+		};
722
+		8A892D142004BAC5BDD0C2341E6D452F /* Build configuration list for PBXNativeTarget "Pods-Trolley App" */ = {
723
+			isa = XCConfigurationList;
724
+			buildConfigurations = (
725
+				73367964D542BFDEE266363279883884 /* Debug */,
726
+				ADED795A3A5F72281E91FB612D07F320 /* Release */,
727
+			);
728
+			defaultConfigurationIsVisible = 0;
729
+			defaultConfigurationName = Release;
730
+		};
731
+/* End XCConfigurationList section */
732
+	};
733
+	rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */;
734
+}

+ 60
- 0
Pods/Pods.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/Alamofire.xcscheme View File

@@ -0,0 +1,60 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1100"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForAnalyzing = "YES"
11
+            buildForTesting = "YES"
12
+            buildForRunning = "YES"
13
+            buildForProfiling = "YES"
14
+            buildForArchiving = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "EAAA1AD3A8A1B59AB91319EE40752C6D"
18
+               BuildableName = "Alamofire.framework"
19
+               BlueprintName = "Alamofire"
20
+               ReferencedContainer = "container:Pods.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
27
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
28
+      shouldUseLaunchSchemeArgsEnv = "YES"
29
+      buildConfiguration = "Debug">
30
+      <AdditionalOptions>
31
+      </AdditionalOptions>
32
+   </TestAction>
33
+   <LaunchAction
34
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
35
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
36
+      launchStyle = "0"
37
+      useCustomWorkingDirectory = "NO"
38
+      ignoresPersistentStateOnLaunch = "NO"
39
+      debugDocumentVersioning = "YES"
40
+      debugServiceExtension = "internal"
41
+      buildConfiguration = "Debug"
42
+      allowLocationSimulation = "YES">
43
+      <AdditionalOptions>
44
+      </AdditionalOptions>
45
+   </LaunchAction>
46
+   <ProfileAction
47
+      savedToolIdentifier = ""
48
+      useCustomWorkingDirectory = "NO"
49
+      debugDocumentVersioning = "YES"
50
+      buildConfiguration = "Release"
51
+      shouldUseLaunchSchemeArgsEnv = "YES">
52
+   </ProfileAction>
53
+   <AnalyzeAction
54
+      buildConfiguration = "Debug">
55
+   </AnalyzeAction>
56
+   <ArchiveAction
57
+      buildConfiguration = "Release"
58
+      revealArchiveInOrganizer = "YES">
59
+   </ArchiveAction>
60
+</Scheme>

+ 58
- 0
Pods/Pods.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/Pods-Trolley App.xcscheme View File

@@ -0,0 +1,58 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1100"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForTesting = "YES"
11
+            buildForRunning = "YES"
12
+            buildForProfiling = "YES"
13
+            buildForArchiving = "YES"
14
+            buildForAnalyzing = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "171A0B9EEB8AE346EB29A7957BE4577E"
18
+               BuildableName = "Pods_Trolley_App.framework"
19
+               BlueprintName = "Pods-Trolley App"
20
+               ReferencedContainer = "container:Pods.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      buildConfiguration = "Debug"
27
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
+      shouldUseLaunchSchemeArgsEnv = "YES">
30
+      <Testables>
31
+      </Testables>
32
+   </TestAction>
33
+   <LaunchAction
34
+      buildConfiguration = "Debug"
35
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37
+      launchStyle = "0"
38
+      useCustomWorkingDirectory = "NO"
39
+      ignoresPersistentStateOnLaunch = "NO"
40
+      debugDocumentVersioning = "YES"
41
+      debugServiceExtension = "internal"
42
+      allowLocationSimulation = "YES">
43
+   </LaunchAction>
44
+   <ProfileAction
45
+      buildConfiguration = "Release"
46
+      shouldUseLaunchSchemeArgsEnv = "YES"
47
+      savedToolIdentifier = ""
48
+      useCustomWorkingDirectory = "NO"
49
+      debugDocumentVersioning = "YES">
50
+   </ProfileAction>
51
+   <AnalyzeAction
52
+      buildConfiguration = "Debug">
53
+   </AnalyzeAction>
54
+   <ArchiveAction
55
+      buildConfiguration = "Release"
56
+      revealArchiveInOrganizer = "YES">
57
+   </ArchiveAction>
58
+</Scheme>

+ 25
- 0
Pods/Pods.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/xcschememanagement.plist View File

@@ -0,0 +1,25 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>SchemeUserState</key>
6
+	<dict>
7
+		<key>Alamofire.xcscheme</key>
8
+		<dict>
9
+			<key>isShown</key>
10
+			<false/>
11
+			<key>orderHint</key>
12
+			<integer>0</integer>
13
+		</dict>
14
+		<key>Pods-Trolley App.xcscheme</key>
15
+		<dict>
16
+			<key>isShown</key>
17
+			<false/>
18
+			<key>orderHint</key>
19
+			<integer>1</integer>
20
+		</dict>
21
+	</dict>
22
+	<key>SuppressBuildableAutocreation</key>
23
+	<dict/>
24
+</dict>
25
+</plist>

+ 26
- 0
Pods/Target Support Files/Alamofire/Alamofire-Info.plist View File

@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+  <key>CFBundleDevelopmentRegion</key>
6
+  <string>en</string>
7
+  <key>CFBundleExecutable</key>
8
+  <string>${EXECUTABLE_NAME}</string>
9
+  <key>CFBundleIdentifier</key>
10
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
11
+  <key>CFBundleInfoDictionaryVersion</key>
12
+  <string>6.0</string>
13
+  <key>CFBundleName</key>
14
+  <string>${PRODUCT_NAME}</string>
15
+  <key>CFBundlePackageType</key>
16
+  <string>FMWK</string>
17
+  <key>CFBundleShortVersionString</key>
18
+  <string>5.0.0</string>
19
+  <key>CFBundleSignature</key>
20
+  <string>????</string>
21
+  <key>CFBundleVersion</key>
22
+  <string>${CURRENT_PROJECT_VERSION}</string>
23
+  <key>NSPrincipalClass</key>
24
+  <string></string>
25
+</dict>
26
+</plist>

+ 5
- 0
Pods/Target Support Files/Alamofire/Alamofire-dummy.m View File

@@ -0,0 +1,5 @@
1
+#import <Foundation/Foundation.h>
2
+@interface PodsDummy_Alamofire : NSObject
3
+@end
4
+@implementation PodsDummy_Alamofire
5
+@end

+ 12
- 0
Pods/Target Support Files/Alamofire/Alamofire-prefix.pch View File

@@ -0,0 +1,12 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+

+ 16
- 0
Pods/Target Support Files/Alamofire/Alamofire-umbrella.h View File

@@ -0,0 +1,16 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+
13
+
14
+FOUNDATION_EXPORT double AlamofireVersionNumber;
15
+FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
16
+

+ 6
- 0
Pods/Target Support Files/Alamofire/Alamofire.modulemap View File

@@ -0,0 +1,6 @@
1
+framework module Alamofire {
2
+  umbrella header "Alamofire-umbrella.h"
3
+
4
+  export *
5
+  module * { export * }
6
+}

+ 11
- 0
Pods/Target Support Files/Alamofire/Alamofire.xcconfig View File

@@ -0,0 +1,11 @@
1
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alamofire
2
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3
+OTHER_LDFLAGS = $(inherited) -framework "CFNetwork"
4
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
5
+PODS_BUILD_DIR = ${BUILD_DIR}
6
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7
+PODS_ROOT = ${SRCROOT}
8
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire
9
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10
+SKIP_INSTALL = YES
11
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 26
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist View File

@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+  <key>CFBundleDevelopmentRegion</key>
6
+  <string>en</string>
7
+  <key>CFBundleExecutable</key>
8
+  <string>${EXECUTABLE_NAME}</string>
9
+  <key>CFBundleIdentifier</key>
10
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
11
+  <key>CFBundleInfoDictionaryVersion</key>
12
+  <string>6.0</string>
13
+  <key>CFBundleName</key>
14
+  <string>${PRODUCT_NAME}</string>
15
+  <key>CFBundlePackageType</key>
16
+  <string>FMWK</string>
17
+  <key>CFBundleShortVersionString</key>
18
+  <string>1.0.0</string>
19
+  <key>CFBundleSignature</key>
20
+  <string>????</string>
21
+  <key>CFBundleVersion</key>
22
+  <string>${CURRENT_PROJECT_VERSION}</string>
23
+  <key>NSPrincipalClass</key>
24
+  <string></string>
25
+</dict>
26
+</plist>

+ 26
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.markdown View File

@@ -0,0 +1,26 @@
1
+# Acknowledgements
2
+This application makes use of the following third party libraries:
3
+
4
+## Alamofire
5
+
6
+Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
7
+
8
+Permission is hereby granted, free of charge, to any person obtaining a copy
9
+of this software and associated documentation files (the "Software"), to deal
10
+in the Software without restriction, including without limitation the rights
11
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+copies of the Software, and to permit persons to whom the Software is
13
+furnished to do so, subject to the following conditions:
14
+
15
+The above copyright notice and this permission notice shall be included in
16
+all copies or substantial portions of the Software.
17
+
18
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+THE SOFTWARE.
25
+
26
+Generated by CocoaPods - https://cocoapods.org

+ 58
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.plist View File

@@ -0,0 +1,58 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>PreferenceSpecifiers</key>
6
+	<array>
7
+		<dict>
8
+			<key>FooterText</key>
9
+			<string>This application makes use of the following third party libraries:</string>
10
+			<key>Title</key>
11
+			<string>Acknowledgements</string>
12
+			<key>Type</key>
13
+			<string>PSGroupSpecifier</string>
14
+		</dict>
15
+		<dict>
16
+			<key>FooterText</key>
17
+			<string>Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
18
+
19
+Permission is hereby granted, free of charge, to any person obtaining a copy
20
+of this software and associated documentation files (the "Software"), to deal
21
+in the Software without restriction, including without limitation the rights
22
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+copies of the Software, and to permit persons to whom the Software is
24
+furnished to do so, subject to the following conditions:
25
+
26
+The above copyright notice and this permission notice shall be included in
27
+all copies or substantial portions of the Software.
28
+
29
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35
+THE SOFTWARE.
36
+</string>
37
+			<key>License</key>
38
+			<string>MIT</string>
39
+			<key>Title</key>
40
+			<string>Alamofire</string>
41
+			<key>Type</key>
42
+			<string>PSGroupSpecifier</string>
43
+		</dict>
44
+		<dict>
45
+			<key>FooterText</key>
46
+			<string>Generated by CocoaPods - https://cocoapods.org</string>
47
+			<key>Title</key>
48
+			<string></string>
49
+			<key>Type</key>
50
+			<string>PSGroupSpecifier</string>
51
+		</dict>
52
+	</array>
53
+	<key>StringsTable</key>
54
+	<string>Acknowledgements</string>
55
+	<key>Title</key>
56
+	<string>Acknowledgements</string>
57
+</dict>
58
+</plist>

+ 5
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-dummy.m View File

@@ -0,0 +1,5 @@
1
+#import <Foundation/Foundation.h>
2
+@interface PodsDummy_Pods_Trolley_App : NSObject
3
+@end
4
+@implementation PodsDummy_Pods_Trolley_App
5
+@end

+ 2
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-input-files.xcfilelist View File

@@ -0,0 +1,2 @@
1
+${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh
2
+${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework

+ 1
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-output-files.xcfilelist View File

@@ -0,0 +1 @@
1
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework

+ 2
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-input-files.xcfilelist View File

@@ -0,0 +1,2 @@
1
+${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh
2
+${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework

+ 1
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-output-files.xcfilelist View File

@@ -0,0 +1 @@
1
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework

+ 171
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh View File

@@ -0,0 +1,171 @@
1
+#!/bin/sh
2
+set -e
3
+set -u
4
+set -o pipefail
5
+
6
+function on_error {
7
+  echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
8
+}
9
+trap 'on_error $LINENO' ERR
10
+
11
+if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
12
+  # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
13
+  # frameworks to, so exit 0 (signalling the script phase was successful).
14
+  exit 0
15
+fi
16
+
17
+echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
18
+mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
19
+
20
+COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
21
+SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
22
+
23
+# Used as a return value for each invocation of `strip_invalid_archs` function.
24
+STRIP_BINARY_RETVAL=0
25
+
26
+# This protects against multiple targets copying the same framework dependency at the same time. The solution
27
+# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
28
+RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
29
+
30
+# Copies and strips a vendored framework
31
+install_framework()
32
+{
33
+  if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
34
+    local source="${BUILT_PRODUCTS_DIR}/$1"
35
+  elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
36
+    local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
37
+  elif [ -r "$1" ]; then
38
+    local source="$1"
39
+  fi
40
+
41
+  local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
42
+
43
+  if [ -L "${source}" ]; then
44
+    echo "Symlinked..."
45
+    source="$(readlink "${source}")"
46
+  fi
47
+
48
+  # Use filter instead of exclude so missing patterns don't throw errors.
49
+  echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
50
+  rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
51
+
52
+  local basename
53
+  basename="$(basename -s .framework "$1")"
54
+  binary="${destination}/${basename}.framework/${basename}"
55
+
56
+  if ! [ -r "$binary" ]; then
57
+    binary="${destination}/${basename}"
58
+  elif [ -L "${binary}" ]; then
59
+    echo "Destination binary is symlinked..."
60
+    dirname="$(dirname "${binary}")"
61
+    binary="${dirname}/$(readlink "${binary}")"
62
+  fi
63
+
64
+  # Strip invalid architectures so "fat" simulator / device frameworks work on device
65
+  if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
66
+    strip_invalid_archs "$binary"
67
+  fi
68
+
69
+  # Resign the code if required by the build settings to avoid unstable apps
70
+  code_sign_if_enabled "${destination}/$(basename "$1")"
71
+
72
+  # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
73
+  if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
74
+    local swift_runtime_libs
75
+    swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u)
76
+    for lib in $swift_runtime_libs; do
77
+      echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
78
+      rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
79
+      code_sign_if_enabled "${destination}/${lib}"
80
+    done
81
+  fi
82
+}
83
+
84
+# Copies and strips a vendored dSYM
85
+install_dsym() {
86
+  local source="$1"
87
+  if [ -r "$source" ]; then
88
+    # Copy the dSYM into a the targets temp dir.
89
+    echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
90
+    rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
91
+
92
+    local basename
93
+    basename="$(basename -s .framework.dSYM "$source")"
94
+    binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}"
95
+
96
+    # Strip invalid architectures so "fat" simulator / device frameworks work on device
97
+    if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then
98
+      strip_invalid_archs "$binary"
99
+    fi
100
+
101
+    if [[ $STRIP_BINARY_RETVAL == 1 ]]; then
102
+      # Move the stripped file into its final destination.
103
+      echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
104
+      rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
105
+    else
106
+      # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
107
+      touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM"
108
+    fi
109
+  fi
110
+}
111
+
112
+# Copies the bcsymbolmap files of a vendored framework
113
+install_bcsymbolmap() {
114
+    local bcsymbolmap_path="$1"
115
+    local destination="${BUILT_PRODUCTS_DIR}"
116
+    echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}""
117
+    rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"
118
+}
119
+
120
+# Signs a framework with the provided identity
121
+code_sign_if_enabled() {
122
+  if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
123
+    # Use the current code_sign_identity
124
+    echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
125
+    local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
126
+
127
+    if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
128
+      code_sign_cmd="$code_sign_cmd &"
129
+    fi
130
+    echo "$code_sign_cmd"
131
+    eval "$code_sign_cmd"
132
+  fi
133
+}
134
+
135
+# Strip invalid architectures
136
+strip_invalid_archs() {
137
+  binary="$1"
138
+  # Get architectures for current target binary
139
+  binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
140
+  # Intersect them with the architectures we are building for
141
+  intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
142
+  # If there are no archs supported by this binary then warn the user
143
+  if [[ -z "$intersected_archs" ]]; then
144
+    echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
145
+    STRIP_BINARY_RETVAL=0
146
+    return
147
+  fi
148
+  stripped=""
149
+  for arch in $binary_archs; do
150
+    if ! [[ "${ARCHS}" == *"$arch"* ]]; then
151
+      # Strip non-valid architectures in-place
152
+      lipo -remove "$arch" -output "$binary" "$binary"
153
+      stripped="$stripped $arch"
154
+    fi
155
+  done
156
+  if [[ "$stripped" ]]; then
157
+    echo "Stripped $binary of architectures:$stripped"
158
+  fi
159
+  STRIP_BINARY_RETVAL=1
160
+}
161
+
162
+
163
+if [[ "$CONFIGURATION" == "Debug" ]]; then
164
+  install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
165
+fi
166
+if [[ "$CONFIGURATION" == "Release" ]]; then
167
+  install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
168
+fi
169
+if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
170
+  wait
171
+fi

+ 16
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-umbrella.h View File

@@ -0,0 +1,16 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+
13
+
14
+FOUNDATION_EXPORT double Pods_Trolley_AppVersionNumber;
15
+FOUNDATION_EXPORT const unsigned char Pods_Trolley_AppVersionString[];
16
+

+ 12
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.debug.xcconfig View File

@@ -0,0 +1,12 @@
1
+ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire"
3
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers"
5
+LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6
+OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork"
7
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8
+PODS_BUILD_DIR = ${BUILD_DIR}
9
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10
+PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11
+PODS_ROOT = ${SRCROOT}/Pods
12
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 6
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap View File

@@ -0,0 +1,6 @@
1
+framework module Pods_Trolley_App {
2
+  umbrella header "Pods-Trolley App-umbrella.h"
3
+
4
+  export *
5
+  module * { export * }
6
+}

+ 12
- 0
Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.release.xcconfig View File

@@ -0,0 +1,12 @@
1
+ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire"
3
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers"
5
+LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6
+OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork"
7
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8
+PODS_BUILD_DIR = ${BUILD_DIR}
9
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10
+PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11
+PODS_ROOT = ${SRCROOT}/Pods
12
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 199
- 0
Trolley App.xcodeproj/project.pbxproj View File

@@ -13,8 +13,61 @@
13 13
 		5B319F07235DDC06009AD1A9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B319F05235DDC06009AD1A9 /* Main.storyboard */; };
14 14
 		5B319F09235DDC07009AD1A9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5B319F08235DDC07009AD1A9 /* Assets.xcassets */; };
15 15
 		5B319F0C235DDC07009AD1A9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B319F0A235DDC07009AD1A9 /* LaunchScreen.storyboard */; };
16
+		8F9E2832DC2BA6A7618E6A74 /* Pods_Trolley_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 81B1A882D3419AFAB560DA6C /* Pods_Trolley_App.framework */; };
16 17
 /* End PBXBuildFile section */
17 18
 
19
+/* Begin PBXContainerItemProxy section */
20
+		5B68B700238A192200E3B2F8 /* PBXContainerItemProxy */ = {
21
+			isa = PBXContainerItemProxy;
22
+			containerPortal = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
23
+			proxyType = 2;
24
+			remoteGlobalIDString = F8111E3319A95C8B0040E7D1;
25
+			remoteInfo = "Alamofire iOS";
26
+		};
27
+		5B68B702238A192200E3B2F8 /* PBXContainerItemProxy */ = {
28
+			isa = PBXContainerItemProxy;
29
+			containerPortal = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
30
+			proxyType = 2;
31
+			remoteGlobalIDString = F8111E3E19A95C8B0040E7D1;
32
+			remoteInfo = "Alamofire iOS Tests";
33
+		};
34
+		5B68B704238A192200E3B2F8 /* PBXContainerItemProxy */ = {
35
+			isa = PBXContainerItemProxy;
36
+			containerPortal = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
37
+			proxyType = 2;
38
+			remoteGlobalIDString = 4DD67C0B1A5C55C900ED2280;
39
+			remoteInfo = "Alamofire macOS";
40
+		};
41
+		5B68B706238A192200E3B2F8 /* PBXContainerItemProxy */ = {
42
+			isa = PBXContainerItemProxy;
43
+			containerPortal = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
44
+			proxyType = 2;
45
+			remoteGlobalIDString = F829C6B21A7A94F100A2CD59;
46
+			remoteInfo = "Alamofire macOS Tests";
47
+		};
48
+		5B68B708238A192200E3B2F8 /* PBXContainerItemProxy */ = {
49
+			isa = PBXContainerItemProxy;
50
+			containerPortal = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
51
+			proxyType = 2;
52
+			remoteGlobalIDString = 4CF626EF1BA7CB3E0011A099;
53
+			remoteInfo = "Alamofire tvOS";
54
+		};
55
+		5B68B70A238A192200E3B2F8 /* PBXContainerItemProxy */ = {
56
+			isa = PBXContainerItemProxy;
57
+			containerPortal = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
58
+			proxyType = 2;
59
+			remoteGlobalIDString = 4CF626F81BA7CB3E0011A099;
60
+			remoteInfo = "Alamofire tvOS Tests";
61
+		};
62
+		5B68B70C238A192200E3B2F8 /* PBXContainerItemProxy */ = {
63
+			isa = PBXContainerItemProxy;
64
+			containerPortal = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
65
+			proxyType = 2;
66
+			remoteGlobalIDString = E4202FE01B667AA100C997FB;
67
+			remoteInfo = "Alamofire watchOS";
68
+		};
69
+/* End PBXContainerItemProxy section */
70
+
18 71
 /* Begin PBXFileReference section */
19 72
 		5B319EFC235DDC06009AD1A9 /* Trolley App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Trolley App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
20 73
 		5B319EFF235DDC06009AD1A9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -24,6 +77,10 @@
24 77
 		5B319F08235DDC07009AD1A9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
25 78
 		5B319F0B235DDC07009AD1A9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
26 79
 		5B319F0D235DDC07009AD1A9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
80
+		5B34A0553F2D64D544D88F6B /* Pods-Trolley App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Trolley App.release.xcconfig"; path = "Target Support Files/Pods-Trolley App/Pods-Trolley App.release.xcconfig"; sourceTree = "<group>"; };
81
+		5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Alamofire.xcodeproj; path = Carthage/Checkouts/Alamofire/Alamofire.xcodeproj; sourceTree = "<group>"; };
82
+		81B1A882D3419AFAB560DA6C /* Pods_Trolley_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Trolley_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83
+		FA591BC66D7B1821D3A6608E /* Pods-Trolley App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Trolley App.debug.xcconfig"; path = "Target Support Files/Pods-Trolley App/Pods-Trolley App.debug.xcconfig"; sourceTree = "<group>"; };
27 84
 /* End PBXFileReference section */
28 85
 
29 86
 /* Begin PBXFrameworksBuildPhase section */
@@ -31,17 +88,30 @@
31 88
 			isa = PBXFrameworksBuildPhase;
32 89
 			buildActionMask = 2147483647;
33 90
 			files = (
91
+				8F9E2832DC2BA6A7618E6A74 /* Pods_Trolley_App.framework in Frameworks */,
34 92
 			);
35 93
 			runOnlyForDeploymentPostprocessing = 0;
36 94
 		};
37 95
 /* End PBXFrameworksBuildPhase section */
38 96
 
39 97
 /* Begin PBXGroup section */
98
+		5665F60D6472583889B09543 /* Pods */ = {
99
+			isa = PBXGroup;
100
+			children = (
101
+				FA591BC66D7B1821D3A6608E /* Pods-Trolley App.debug.xcconfig */,
102
+				5B34A0553F2D64D544D88F6B /* Pods-Trolley App.release.xcconfig */,
103
+			);
104
+			name = Pods;
105
+			path = Pods;
106
+			sourceTree = "<group>";
107
+		};
40 108
 		5B319EF3235DDC06009AD1A9 = {
41 109
 			isa = PBXGroup;
42 110
 			children = (
43 111
 				5B319EFE235DDC06009AD1A9 /* Trolley App */,
44 112
 				5B319EFD235DDC06009AD1A9 /* Products */,
113
+				5B68B6F5238A192200E3B2F8 /* Frameworks */,
114
+				5665F60D6472583889B09543 /* Pods */,
45 115
 			);
46 116
 			sourceTree = "<group>";
47 117
 		};
@@ -67,6 +137,29 @@
67 137
 			path = "Trolley App";
68 138
 			sourceTree = "<group>";
69 139
 		};
140
+		5B68B6F5238A192200E3B2F8 /* Frameworks */ = {
141
+			isa = PBXGroup;
142
+			children = (
143
+				5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */,
144
+				81B1A882D3419AFAB560DA6C /* Pods_Trolley_App.framework */,
145
+			);
146
+			name = Frameworks;
147
+			sourceTree = "<group>";
148
+		};
149
+		5B68B6F7238A192200E3B2F8 /* Products */ = {
150
+			isa = PBXGroup;
151
+			children = (
152
+				5B68B701238A192200E3B2F8 /* Alamofire.framework */,
153
+				5B68B703238A192200E3B2F8 /* Alamofire iOS Tests.xctest */,
154
+				5B68B705238A192200E3B2F8 /* Alamofire.framework */,
155
+				5B68B707238A192200E3B2F8 /* Alamofire macOS Tests.xctest */,
156
+				5B68B709238A192200E3B2F8 /* Alamofire.framework */,
157
+				5B68B70B238A192200E3B2F8 /* Alamofire tvOS Tests.xctest */,
158
+				5B68B70D238A192200E3B2F8 /* Alamofire.framework */,
159
+			);
160
+			name = Products;
161
+			sourceTree = "<group>";
162
+		};
70 163
 /* End PBXGroup section */
71 164
 
72 165
 /* Begin PBXNativeTarget section */
@@ -74,9 +167,11 @@
74 167
 			isa = PBXNativeTarget;
75 168
 			buildConfigurationList = 5B319F10235DDC07009AD1A9 /* Build configuration list for PBXNativeTarget "Trolley App" */;
76 169
 			buildPhases = (
170
+				0F224B9A21F43DC7E5BDBB18 /* [CP] Check Pods Manifest.lock */,
77 171
 				5B319EF8235DDC06009AD1A9 /* Sources */,
78 172
 				5B319EF9235DDC06009AD1A9 /* Frameworks */,
79 173
 				5B319EFA235DDC06009AD1A9 /* Resources */,
174
+				79D0F25373565F1AA2E6656F /* [CP] Embed Pods Frameworks */,
80 175
 			);
81 176
 			buildRules = (
82 177
 			);
@@ -113,6 +208,12 @@
113 208
 			mainGroup = 5B319EF3235DDC06009AD1A9;
114 209
 			productRefGroup = 5B319EFD235DDC06009AD1A9 /* Products */;
115 210
 			projectDirPath = "";
211
+			projectReferences = (
212
+				{
213
+					ProductGroup = 5B68B6F7238A192200E3B2F8 /* Products */;
214
+					ProjectRef = 5B68B6F6238A192200E3B2F8 /* Alamofire.xcodeproj */;
215
+				},
216
+			);
116 217
 			projectRoot = "";
117 218
 			targets = (
118 219
 				5B319EFB235DDC06009AD1A9 /* Trolley App */,
@@ -120,6 +221,58 @@
120 221
 		};
121 222
 /* End PBXProject section */
122 223
 
224
+/* Begin PBXReferenceProxy section */
225
+		5B68B701238A192200E3B2F8 /* Alamofire.framework */ = {
226
+			isa = PBXReferenceProxy;
227
+			fileType = wrapper.framework;
228
+			path = Alamofire.framework;
229
+			remoteRef = 5B68B700238A192200E3B2F8 /* PBXContainerItemProxy */;
230
+			sourceTree = BUILT_PRODUCTS_DIR;
231
+		};
232
+		5B68B703238A192200E3B2F8 /* Alamofire iOS Tests.xctest */ = {
233
+			isa = PBXReferenceProxy;
234
+			fileType = wrapper.cfbundle;
235
+			path = "Alamofire iOS Tests.xctest";
236
+			remoteRef = 5B68B702238A192200E3B2F8 /* PBXContainerItemProxy */;
237
+			sourceTree = BUILT_PRODUCTS_DIR;
238
+		};
239
+		5B68B705238A192200E3B2F8 /* Alamofire.framework */ = {
240
+			isa = PBXReferenceProxy;
241
+			fileType = wrapper.framework;
242
+			path = Alamofire.framework;
243
+			remoteRef = 5B68B704238A192200E3B2F8 /* PBXContainerItemProxy */;
244
+			sourceTree = BUILT_PRODUCTS_DIR;
245
+		};
246
+		5B68B707238A192200E3B2F8 /* Alamofire macOS Tests.xctest */ = {
247
+			isa = PBXReferenceProxy;
248
+			fileType = wrapper.cfbundle;
249
+			path = "Alamofire macOS Tests.xctest";
250
+			remoteRef = 5B68B706238A192200E3B2F8 /* PBXContainerItemProxy */;
251
+			sourceTree = BUILT_PRODUCTS_DIR;
252
+		};
253
+		5B68B709238A192200E3B2F8 /* Alamofire.framework */ = {
254
+			isa = PBXReferenceProxy;
255
+			fileType = wrapper.framework;
256
+			path = Alamofire.framework;
257
+			remoteRef = 5B68B708238A192200E3B2F8 /* PBXContainerItemProxy */;
258
+			sourceTree = BUILT_PRODUCTS_DIR;
259
+		};
260
+		5B68B70B238A192200E3B2F8 /* Alamofire tvOS Tests.xctest */ = {
261
+			isa = PBXReferenceProxy;
262
+			fileType = wrapper.cfbundle;
263
+			path = "Alamofire tvOS Tests.xctest";
264
+			remoteRef = 5B68B70A238A192200E3B2F8 /* PBXContainerItemProxy */;
265
+			sourceTree = BUILT_PRODUCTS_DIR;
266
+		};
267
+		5B68B70D238A192200E3B2F8 /* Alamofire.framework */ = {
268
+			isa = PBXReferenceProxy;
269
+			fileType = wrapper.framework;
270
+			path = Alamofire.framework;
271
+			remoteRef = 5B68B70C238A192200E3B2F8 /* PBXContainerItemProxy */;
272
+			sourceTree = BUILT_PRODUCTS_DIR;
273
+		};
274
+/* End PBXReferenceProxy section */
275
+
123 276
 /* Begin PBXResourcesBuildPhase section */
124 277
 		5B319EFA235DDC06009AD1A9 /* Resources */ = {
125 278
 			isa = PBXResourcesBuildPhase;
@@ -133,6 +286,48 @@
133 286
 		};
134 287
 /* End PBXResourcesBuildPhase section */
135 288
 
289
+/* Begin PBXShellScriptBuildPhase section */
290
+		0F224B9A21F43DC7E5BDBB18 /* [CP] Check Pods Manifest.lock */ = {
291
+			isa = PBXShellScriptBuildPhase;
292
+			buildActionMask = 2147483647;
293
+			files = (
294
+			);
295
+			inputFileListPaths = (
296
+			);
297
+			inputPaths = (
298
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
299
+				"${PODS_ROOT}/Manifest.lock",
300
+			);
301
+			name = "[CP] Check Pods Manifest.lock";
302
+			outputFileListPaths = (
303
+			);
304
+			outputPaths = (
305
+				"$(DERIVED_FILE_DIR)/Pods-Trolley App-checkManifestLockResult.txt",
306
+			);
307
+			runOnlyForDeploymentPostprocessing = 0;
308
+			shellPath = /bin/sh;
309
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
310
+			showEnvVarsInLog = 0;
311
+		};
312
+		79D0F25373565F1AA2E6656F /* [CP] Embed Pods Frameworks */ = {
313
+			isa = PBXShellScriptBuildPhase;
314
+			buildActionMask = 2147483647;
315
+			files = (
316
+			);
317
+			inputFileListPaths = (
318
+				"${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
319
+			);
320
+			name = "[CP] Embed Pods Frameworks";
321
+			outputFileListPaths = (
322
+				"${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
323
+			);
324
+			runOnlyForDeploymentPostprocessing = 0;
325
+			shellPath = /bin/sh;
326
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh\"\n";
327
+			showEnvVarsInLog = 0;
328
+		};
329
+/* End PBXShellScriptBuildPhase section */
330
+
136 331
 /* Begin PBXSourcesBuildPhase section */
137 332
 		5B319EF8235DDC06009AD1A9 /* Sources */ = {
138 333
 			isa = PBXSourcesBuildPhase;
@@ -282,9 +477,11 @@
282 477
 		};
283 478
 		5B319F11235DDC07009AD1A9 /* Debug */ = {
284 479
 			isa = XCBuildConfiguration;
480
+			baseConfigurationReference = FA591BC66D7B1821D3A6608E /* Pods-Trolley App.debug.xcconfig */;
285 481
 			buildSettings = {
286 482
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
287 483
 				CODE_SIGN_STYLE = Automatic;
484
+				DEVELOPMENT_ASSET_PATHS = "";
288 485
 				DEVELOPMENT_TEAM = H67NFWVH5W;
289 486
 				INFOPLIST_FILE = "Trolley App/Info.plist";
290 487
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -300,9 +497,11 @@
300 497
 		};
301 498
 		5B319F12235DDC07009AD1A9 /* Release */ = {
302 499
 			isa = XCBuildConfiguration;
500
+			baseConfigurationReference = 5B34A0553F2D64D544D88F6B /* Pods-Trolley App.release.xcconfig */;
303 501
 			buildSettings = {
304 502
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
305 503
 				CODE_SIGN_STYLE = Automatic;
504
+				DEVELOPMENT_ASSET_PATHS = "";
306 505
 				DEVELOPMENT_TEAM = H67NFWVH5W;
307 506
 				INFOPLIST_FILE = "Trolley App/Info.plist";
308 507
 				LD_RUNPATH_SEARCH_PATHS = (

BIN
Trolley App.xcodeproj/project.xcworkspace/xcuserdata/kendrickmorales.xcuserdatad/UserInterfaceState.xcuserstate View File


BIN
Trolley App.xcodeproj/project.xcworkspace/xcuserdata/stephaniem.ramos.xcuserdatad/UserInterfaceState.xcuserstate View File


+ 1
- 1
Trolley App.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/xcschememanagement.plist View File

@@ -7,7 +7,7 @@
7 7
 		<key>Trolley App.xcscheme_^#shared#^_</key>
8 8
 		<dict>
9 9
 			<key>orderHint</key>
10
-			<integer>0</integer>
10
+			<integer>2</integer>
11 11
 		</dict>
12 12
 	</dict>
13 13
 </dict>

+ 14
- 0
Trolley App.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/xcschememanagement.plist View File

@@ -0,0 +1,14 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>SchemeUserState</key>
6
+	<dict>
7
+		<key>Trolley App.xcscheme_^#shared#^_</key>
8
+		<dict>
9
+			<key>orderHint</key>
10
+			<integer>0</integer>
11
+		</dict>
12
+	</dict>
13
+</dict>
14
+</plist>

+ 10
- 0
Trolley App.xcworkspace/contents.xcworkspacedata View File

@@ -0,0 +1,10 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Workspace
3
+   version = "1.0">
4
+   <FileRef
5
+      location = "group:Trolley App.xcodeproj">
6
+   </FileRef>
7
+   <FileRef
8
+      location = "group:Pods/Pods.xcodeproj">
9
+   </FileRef>
10
+</Workspace>

+ 8
- 0
Trolley App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist View File

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>IDEDidComputeMac32BitWarning</key>
6
+	<true/>
7
+</dict>
8
+</plist>

BIN
Trolley App.xcworkspace/xcuserdata/kendrickmorales.xcuserdatad/UserInterfaceState.xcuserstate View File


BIN
Trolley App/.DS_Store View File


BIN
Trolley App/Assets.xcassets/.DS_Store View File


+ 220
- 18
Trolley App/Base.lproj/Main.storyboard View File

@@ -15,43 +15,58 @@
15 15
                         <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
16 16
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
17 17
                         <subviews>
18
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Trolley IUPI" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5sx-mb-Vhu">
18
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Trolley IUPI" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5sx-mb-Vhu">
19 19
                                 <rect key="frame" x="108" y="90" width="201" height="47"/>
20
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
21 20
                                 <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="40"/>
22 21
                                 <nil key="textColor"/>
23 22
                                 <nil key="highlightedColor"/>
24 23
                             </label>
25
-                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="map" translatesAutoresizingMaskIntoConstraints="NO" id="KQC-gY-9mQ">
26
-                                <rect key="frame" x="7" y="248" width="400" height="400"/>
27
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
24
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="map" translatesAutoresizingMaskIntoConstraints="NO" id="KQC-gY-9mQ">
25
+                                <rect key="frame" x="7" y="247" width="400" height="400"/>
26
+                                <constraints>
27
+                                    <constraint firstAttribute="height" constant="400" id="qfV-As-PC0"/>
28
+                                </constraints>
28 29
                             </imageView>
29
-                            <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OCY-3M-KE5">
30
-                                <rect key="frame" x="71" y="706" width="111" height="47"/>
31
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
32
-                                <color key="backgroundColor" systemColor="systemPinkColor" red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
30
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2cl-Ch-09v">
31
+                                <rect key="frame" x="246" y="705" width="113" height="48"/>
32
+                                <color key="backgroundColor" red="0.77344781159999998" green="0.095710434019999999" blue="0.1044210568" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
33 33
                                 <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="30"/>
34
-                                <state key="normal" title="Paradas">
34
+                                <state key="normal" title="Tracking">
35 35
                                     <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
36 36
                                 </state>
37 37
                                 <connections>
38
-                                    <action selector="paradasButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="esp-QM-yT5"/>
38
+                                    <action selector="trackingButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="bj2-2c-F73"/>
39 39
                                 </connections>
40 40
                             </button>
41
-                            <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2cl-Ch-09v">
42
-                                <rect key="frame" x="246" y="706" width="113" height="47"/>
43
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
44
-                                <color key="backgroundColor" systemColor="systemPinkColor" red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
45
-                                <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="30"/>
46
-                                <state key="normal" title="Tracking">
41
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mCk-tp-oM3">
42
+                                <rect key="frame" x="49" y="705" width="122" height="48"/>
43
+                                <color key="backgroundColor" red="0.76673818005181349" green="0.10930287577585605" blue="0.13850717263181206" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
44
+                                <constraints>
45
+                                    <constraint firstAttribute="width" constant="122" id="6uo-R9-sfc"/>
46
+                                </constraints>
47
+                                <fontDescription key="fontDescription" type="system" pointSize="30"/>
48
+                                <state key="normal" title="Paradas">
47 49
                                     <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
48 50
                                 </state>
49 51
                                 <connections>
50
-                                    <action selector="trackingButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="bj2-2c-F73"/>
52
+                                    <segue destination="hgI-fz-4Vc" kind="show" id="Mi9-kK-bJx"/>
51 53
                                 </connections>
52 54
                             </button>
53 55
                         </subviews>
54 56
                         <color key="backgroundColor" systemColor="secondarySystemGroupedBackgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
57
+                        <constraints>
58
+                            <constraint firstItem="KQC-gY-9mQ" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="7" id="4tK-75-TTb"/>
59
+                            <constraint firstItem="5sx-mb-Vhu" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="7vx-Bc-qCt"/>
60
+                            <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="mCk-tp-oM3" secondAttribute="bottom" constant="109" id="Zs3-P2-qf5"/>
61
+                            <constraint firstItem="5sx-mb-Vhu" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="46" id="aPT-iH-ChZ"/>
62
+                            <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="5sx-mb-Vhu" secondAttribute="trailing" constant="105" id="bal-xX-LWh"/>
63
+                            <constraint firstItem="mCk-tp-oM3" firstAttribute="top" secondItem="KQC-gY-9mQ" secondAttribute="bottom" constant="58" id="exG-uc-qz9"/>
64
+                            <constraint firstItem="mCk-tp-oM3" firstAttribute="top" secondItem="2cl-Ch-09v" secondAttribute="top" id="gOP-zh-EQH"/>
65
+                            <constraint firstItem="KQC-gY-9mQ" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="j43-we-PaR"/>
66
+                            <constraint firstItem="2cl-Ch-09v" firstAttribute="leading" secondItem="mCk-tp-oM3" secondAttribute="trailing" constant="75" id="kgL-iV-9lE"/>
67
+                            <constraint firstItem="mCk-tp-oM3" firstAttribute="bottom" secondItem="2cl-Ch-09v" secondAttribute="bottom" id="oLg-kF-fXQ"/>
68
+                            <constraint firstItem="mCk-tp-oM3" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="49" id="onu-ZL-tE9"/>
69
+                        </constraints>
55 70
                         <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
56 71
                     </view>
57 72
                 </viewController>
@@ -59,6 +74,193 @@
59 74
             </objects>
60 75
             <point key="canvasLocation" x="137.68115942028987" y="133.92857142857142"/>
61 76
         </scene>
77
+        <!--Table View Controller-->
78
+        <scene sceneID="xjP-gs-qNg">
79
+            <objects>
80
+                <tableViewController id="hgI-fz-4Vc" sceneMemberID="viewController">
81
+                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="aZF-XN-g7M">
82
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
83
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
84
+                        <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
85
+                        <sections>
86
+                            <tableViewSection id="R38-7O-YDv">
87
+                                <cells>
88
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="P9j-EK-xET" style="IBUITableViewCellStyleDefault" id="2X4-Of-h3t">
89
+                                        <rect key="frame" x="0.0" y="28" width="414" height="47.5"/>
90
+                                        <autoresizingMask key="autoresizingMask"/>
91
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="2X4-Of-h3t" id="Wcn-H7-bZD">
92
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
93
+                                            <autoresizingMask key="autoresizingMask"/>
94
+                                            <subviews>
95
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 1" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="P9j-EK-xET">
96
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
97
+                                                    <autoresizingMask key="autoresizingMask"/>
98
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
99
+                                                    <nil key="textColor"/>
100
+                                                    <nil key="highlightedColor"/>
101
+                                                </label>
102
+                                            </subviews>
103
+                                        </tableViewCellContentView>
104
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
105
+                                    </tableViewCell>
106
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="sgQ-Td-W7K" style="IBUITableViewCellStyleDefault" id="ZJF-Xk-L5w">
107
+                                        <rect key="frame" x="0.0" y="75.5" width="414" height="47.5"/>
108
+                                        <autoresizingMask key="autoresizingMask"/>
109
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ZJF-Xk-L5w" id="LDz-uT-YYq">
110
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
111
+                                            <autoresizingMask key="autoresizingMask"/>
112
+                                            <subviews>
113
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 2" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="sgQ-Td-W7K">
114
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
115
+                                                    <autoresizingMask key="autoresizingMask"/>
116
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
117
+                                                    <nil key="textColor"/>
118
+                                                    <nil key="highlightedColor"/>
119
+                                                </label>
120
+                                            </subviews>
121
+                                        </tableViewCellContentView>
122
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
123
+                                    </tableViewCell>
124
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="eew-ss-2Z6" style="IBUITableViewCellStyleDefault" id="mcJ-AL-E90">
125
+                                        <rect key="frame" x="0.0" y="123" width="414" height="47.5"/>
126
+                                        <autoresizingMask key="autoresizingMask"/>
127
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="mcJ-AL-E90" id="ze7-eK-QjC">
128
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
129
+                                            <autoresizingMask key="autoresizingMask"/>
130
+                                            <subviews>
131
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 3" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="eew-ss-2Z6">
132
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
133
+                                                    <autoresizingMask key="autoresizingMask"/>
134
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
135
+                                                    <nil key="textColor"/>
136
+                                                    <nil key="highlightedColor"/>
137
+                                                </label>
138
+                                            </subviews>
139
+                                        </tableViewCellContentView>
140
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
141
+                                    </tableViewCell>
142
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="xnN-d4-0tO" style="IBUITableViewCellStyleDefault" id="678-LD-kG7">
143
+                                        <rect key="frame" x="0.0" y="170.5" width="414" height="47.5"/>
144
+                                        <autoresizingMask key="autoresizingMask"/>
145
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="678-LD-kG7" id="jlf-EF-s4X">
146
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
147
+                                            <autoresizingMask key="autoresizingMask"/>
148
+                                            <subviews>
149
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 4" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="xnN-d4-0tO">
150
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
151
+                                                    <autoresizingMask key="autoresizingMask"/>
152
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
153
+                                                    <nil key="textColor"/>
154
+                                                    <nil key="highlightedColor"/>
155
+                                                </label>
156
+                                            </subviews>
157
+                                        </tableViewCellContentView>
158
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
159
+                                    </tableViewCell>
160
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="ozJ-Dd-JVx" style="IBUITableViewCellStyleDefault" id="Qdr-j2-dMl">
161
+                                        <rect key="frame" x="0.0" y="218" width="414" height="47.5"/>
162
+                                        <autoresizingMask key="autoresizingMask"/>
163
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Qdr-j2-dMl" id="f2e-0P-0se">
164
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
165
+                                            <autoresizingMask key="autoresizingMask"/>
166
+                                            <subviews>
167
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 5" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ozJ-Dd-JVx">
168
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
169
+                                                    <autoresizingMask key="autoresizingMask"/>
170
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
171
+                                                    <nil key="textColor"/>
172
+                                                    <nil key="highlightedColor"/>
173
+                                                </label>
174
+                                            </subviews>
175
+                                        </tableViewCellContentView>
176
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
177
+                                    </tableViewCell>
178
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Ubc-k8-qBb" style="IBUITableViewCellStyleDefault" id="GB7-Wu-mms">
179
+                                        <rect key="frame" x="0.0" y="265.5" width="414" height="47.5"/>
180
+                                        <autoresizingMask key="autoresizingMask"/>
181
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="GB7-Wu-mms" id="y0t-d4-gfp">
182
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
183
+                                            <autoresizingMask key="autoresizingMask"/>
184
+                                            <subviews>
185
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 6" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Ubc-k8-qBb">
186
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
187
+                                                    <autoresizingMask key="autoresizingMask"/>
188
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
189
+                                                    <nil key="textColor"/>
190
+                                                    <nil key="highlightedColor"/>
191
+                                                </label>
192
+                                            </subviews>
193
+                                        </tableViewCellContentView>
194
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
195
+                                    </tableViewCell>
196
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="POV-SW-qZU" style="IBUITableViewCellStyleDefault" id="DUL-zs-ndZ">
197
+                                        <rect key="frame" x="0.0" y="313" width="414" height="47.5"/>
198
+                                        <autoresizingMask key="autoresizingMask"/>
199
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="DUL-zs-ndZ" id="jZ3-iB-nx0">
200
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
201
+                                            <autoresizingMask key="autoresizingMask"/>
202
+                                            <subviews>
203
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 7" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="POV-SW-qZU">
204
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
205
+                                                    <autoresizingMask key="autoresizingMask"/>
206
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
207
+                                                    <nil key="textColor"/>
208
+                                                    <nil key="highlightedColor"/>
209
+                                                </label>
210
+                                            </subviews>
211
+                                        </tableViewCellContentView>
212
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
213
+                                    </tableViewCell>
214
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="rmw-VL-c6Q" style="IBUITableViewCellStyleDefault" id="yo5-fl-fbE">
215
+                                        <rect key="frame" x="0.0" y="360.5" width="414" height="47.5"/>
216
+                                        <autoresizingMask key="autoresizingMask"/>
217
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="yo5-fl-fbE" id="FPQ-Tm-a7c">
218
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
219
+                                            <autoresizingMask key="autoresizingMask"/>
220
+                                            <subviews>
221
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 8" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="rmw-VL-c6Q">
222
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
223
+                                                    <autoresizingMask key="autoresizingMask"/>
224
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
225
+                                                    <nil key="textColor"/>
226
+                                                    <nil key="highlightedColor"/>
227
+                                                </label>
228
+                                            </subviews>
229
+                                        </tableViewCellContentView>
230
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
231
+                                    </tableViewCell>
232
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="KbK-VP-nDK" style="IBUITableViewCellStyleDefault" id="aSV-n0-8Tx">
233
+                                        <rect key="frame" x="0.0" y="408" width="414" height="47.5"/>
234
+                                        <autoresizingMask key="autoresizingMask"/>
235
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="aSV-n0-8Tx" id="JG6-UT-I1Z">
236
+                                            <rect key="frame" x="0.0" y="0.0" width="414" height="47.5"/>
237
+                                            <autoresizingMask key="autoresizingMask"/>
238
+                                            <subviews>
239
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Parada 9" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="KbK-VP-nDK">
240
+                                                    <rect key="frame" x="20" y="0.0" width="374" height="47.5"/>
241
+                                                    <autoresizingMask key="autoresizingMask"/>
242
+                                                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
243
+                                                    <nil key="textColor"/>
244
+                                                    <nil key="highlightedColor"/>
245
+                                                </label>
246
+                                            </subviews>
247
+                                        </tableViewCellContentView>
248
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
249
+                                    </tableViewCell>
250
+                                </cells>
251
+                            </tableViewSection>
252
+                        </sections>
253
+                        <connections>
254
+                            <outlet property="dataSource" destination="hgI-fz-4Vc" id="6u1-6B-JNP"/>
255
+                            <outlet property="delegate" destination="hgI-fz-4Vc" id="9Yo-jn-CLd"/>
256
+                        </connections>
257
+                    </tableView>
258
+                    <navigationItem key="navigationItem" id="LCG-h4-cOW"/>
259
+                </tableViewController>
260
+                <placeholder placeholderIdentifier="IBFirstResponder" id="EF3-hv-twl" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
261
+            </objects>
262
+            <point key="canvasLocation" x="874" y="134"/>
263
+        </scene>
62 264
     </scenes>
63 265
     <resources>
64 266
         <image name="map" width="520.5" height="431"/>

+ 28
- 7
Trolley App/ViewController.swift View File

@@ -9,13 +9,17 @@
9 9
 import UIKit
10 10
 import CoreLocation
11 11
 import MapKit
12
+import Alamofire
13
+
14
+
15
+
12 16
 class ViewController: UIViewController,  CLLocationManagerDelegate {
13 17
 
14 18
     var estado = false
15 19
     let locationManager = CLLocationManager()
16
-    
17 20
    
18
-    
21
+   
22
+    var locations: CLLocation!
19 23
     
20 24
     override func viewDidLoad() {
21 25
         super.viewDidLoad()
@@ -33,10 +37,14 @@ class ViewController: UIViewController,  CLLocationManagerDelegate {
33 37
         guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate
34 38
             else { return }
35 39
         print("locations = \(locValue.latitude) \(locValue.longitude)")
40
+        
41
+        
42
+        
36 43
     }
37 44
  
38 45
     
39
-    //botton de las paradas
46
+    
47
+    //botton de las tracking
40 48
     @IBAction func trackingButton(_ sender: UIButton) {
41 49
         
42 50
         // si el estado esta en falso
@@ -48,13 +56,26 @@ class ViewController: UIViewController,  CLLocationManagerDelegate {
48 56
         else{ // si el estado esta en cierto
49 57
              sender.setTitle("Tracking", for: .normal) // cambiamos el texto del boton
50 58
             locationManager.stopUpdatingLocation() // paramos el metodo de capturacion de localizacion
59
+            locations = locationManager.location
60
+            //print("pollo"+"\(latitud.coordinate.latitude)")
61
+           
62
+            
63
+            let location: [String: Any] = ["latitude": locations.coordinate.latitude,"longitude": locations.coordinate.longitude]
64
+       //conect to server and send lat y long
51 65
             
66
+            AF.request("http://136.145.231.39/json-receiver.php", method:.post, parameters: location,encoding: JSONEncoding.default).response{ (response) in
67
+      print(response)
68
+            }
69
+            
70
+        AF.request("http://136.145.231.39/sender2.php").responseJSON { response in
71
+            debugPrint("Response: \(response)")
72
+            
73
+        }
74
+            
75
+        
52 76
             estado = false // se cambia estado de nuevo a falso
53 77
         }
54 78
     }
55
-    
56
-   
57
-    
58
-    
79
+
59 80
 }
60 81