Alamofire.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. import Foundation
  25. /// Global namespace containing API for the `default` `Session` instance.
  26. public enum AF {
  27. // MARK: - Data Request
  28. /// Creates a `DataRequest` using `SessionManager.default` to retrive the contents of the specified `url`
  29. /// using the `method`, `parameters`, `encoding`, and `headers` provided.
  30. ///
  31. /// - Parameters:
  32. /// - url: The `URLConvertible` value.
  33. /// - method: The `HTTPMethod`, `.get` by default.
  34. /// - parameters: The `Parameters`, `nil` by default.
  35. /// - encoding: The `ParameterEncoding`, `URLEncoding.default` by default.
  36. /// - headers: The `HTTPHeaders`, `nil` by default.
  37. /// - Returns: The created `DataRequest`.
  38. public static func request(_ url: URLConvertible,
  39. method: HTTPMethod = .get,
  40. parameters: Parameters? = nil,
  41. encoding: ParameterEncoding = URLEncoding.default,
  42. headers: HTTPHeaders? = nil) -> DataRequest {
  43. return Session.default.request(url,
  44. method: method,
  45. parameters: parameters,
  46. encoding: encoding,
  47. headers: headers)
  48. }
  49. /// Creates a `DataRequest` using `SessionManager.default` to retrive the contents of the specified `url`
  50. /// using the `method`, `parameters`, `encoding`, and `headers` provided.
  51. ///
  52. /// - Parameters:
  53. /// - url: The `URLConvertible` value.
  54. /// - method: The `HTTPMethod`, `.get` by default.
  55. /// - parameters: The `Encodable` parameters, `nil` by default.
  56. /// - encoding: The `ParameterEncoding`, `URLEncodedFormParameterEncoder.default` by default.
  57. /// - headers: The `HTTPHeaders`, `nil` by default.
  58. /// - Returns: The created `DataRequest`.
  59. public static func request<Parameters: Encodable>(_ url: URLConvertible,
  60. method: HTTPMethod = .get,
  61. parameters: Parameters? = nil,
  62. encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
  63. headers: HTTPHeaders? = nil) -> DataRequest {
  64. return Session.default.request(url,
  65. method: method,
  66. parameters: parameters,
  67. encoder: encoder,
  68. headers: headers)
  69. }
  70. /// Creates a `DataRequest` using `SessionManager.default` to execute the specified `urlRequest`.
  71. ///
  72. /// - Parameter urlRequest: The `URLRequestConvertible` value.
  73. /// - Returns: The created `DataRequest`.
  74. public static func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
  75. return Session.default.request(urlRequest)
  76. }
  77. // MARK: - Download Request
  78. /// Creates a `DownloadRequest` using `SessionManager.default` to download the contents of the specified `url` to
  79. /// the provided `destination` using the `method`, `parameters`, `encoding`, and `headers` provided.
  80. ///
  81. /// If `destination` is not specified, the download will remain at the temporary location determined by the
  82. /// underlying `URLSession`.
  83. ///
  84. /// - Parameters:
  85. /// - url: The `URLConvertible` value.
  86. /// - method: The `HTTPMethod`, `.get` by default.
  87. /// - parameters: The `Parameters`, `nil` by default.
  88. /// - encoding: The `ParameterEncoding`, `URLEncoding.default` by default.
  89. /// - headers: The `HTTPHeaders`, `nil` by default.
  90. /// - destination: The `DownloadRequest.Destination` closure used the determine the destination of the downloaded
  91. /// file. `nil` by default.
  92. /// - Returns: The created `DownloadRequest`.
  93. public static func download(_ url: URLConvertible,
  94. method: HTTPMethod = .get,
  95. parameters: Parameters? = nil,
  96. encoding: ParameterEncoding = URLEncoding.default,
  97. headers: HTTPHeaders? = nil,
  98. to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
  99. return Session.default.download(url,
  100. method: method,
  101. parameters: parameters,
  102. encoding: encoding,
  103. headers: headers,
  104. to: destination)
  105. }
  106. /// Creates a `DownloadRequest` using `SessionManager.default` to download the contents of the specified `url` to
  107. /// the provided `destination` using the `method`, encodable `parameters`, `encoder`, and `headers` provided.
  108. ///
  109. /// If `destination` is not specified, the download will remain at the temporary location determined by the
  110. /// underlying `URLSession`.
  111. ///
  112. /// - Parameters:
  113. /// - url: The `URLConvertible` value.
  114. /// - method: The `HTTPMethod`, `.get` by default.
  115. /// - parameters: The `Encodable` parameters, `nil` by default.
  116. /// - encoder: The `ParameterEncoder`, `URLEncodedFormParameterEncoder.default` by default.
  117. /// - headers: The `HTTPHeaders`, `nil` by default.
  118. /// - destination: The `DownloadRequest.Destination` closure used the determine the destination of the downloaded
  119. /// file. `nil` by default.
  120. /// - Returns: The created `DownloadRequest`.
  121. public static func download<Parameters: Encodable>(_ url: URLConvertible,
  122. method: HTTPMethod = .get,
  123. parameters: Parameters? = nil,
  124. encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
  125. headers: HTTPHeaders? = nil,
  126. to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
  127. return Session.default.download(url,
  128. method: method,
  129. parameters: parameters,
  130. encoder: encoder,
  131. headers: headers,
  132. to: destination)
  133. }
  134. // MARK: URLRequest
  135. /// Creates a `DownloadRequest` using `SessionManager.default` to execute the specified `urlRequest` and download
  136. /// the result to the provided `destination`.
  137. ///
  138. /// - Parameters:
  139. /// - urlRequest: The `URLRequestConvertible` value.
  140. /// - destination: The `DownloadRequest.Destination` closure used the determine the destination of the downloaded
  141. /// file. `nil` by default.
  142. /// - Returns: The created `DownloadRequest`.
  143. public static func download(_ urlRequest: URLRequestConvertible,
  144. to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
  145. return Session.default.download(urlRequest, to: destination)
  146. }
  147. // MARK: Resume Data
  148. /// Creates a `DownloadRequest` using the `SessionManager.default` from the `resumeData` produced from a previous
  149. /// `DownloadRequest` cancellation to retrieve the contents of the original request and save them to the `destination`.
  150. ///
  151. /// If `destination` is not specified, the contents will remain in the temporary location determined by the
  152. /// underlying URL session.
  153. ///
  154. /// 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),
  155. /// `resumeData` is broken on background URL session configurations. There's an underlying bug in the `resumeData`
  156. /// generation logic where the data is written incorrectly and will always fail to resume the download. For more
  157. /// information about the bug and possible workarounds, please refer to the [this Stack Overflow post](http://stackoverflow.com/a/39347461/1342462).
  158. ///
  159. /// - Parameters:
  160. /// - resumeData: The resume `Data`. This is an opaque blob produced by `URLSessionDownloadTask` when a task is
  161. /// cancelled. See [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel)
  162. /// for more information.
  163. /// - destination: The `DownloadRequest.Destination` closure used to determine the destination of the downloaded
  164. /// file. `nil` by default.
  165. /// - Returns: The created `DownloadRequest`.
  166. public static func download(resumingWith resumeData: Data,
  167. to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
  168. return Session.default.download(resumingWith: resumeData, to: destination)
  169. }
  170. // MARK: - Upload Request
  171. // MARK: File
  172. /// Creates an `UploadRequest` using `SessionManager.default` to upload the contents of the `fileURL` specified
  173. /// using the `url`, `method` and `headers` provided.
  174. ///
  175. /// - Parameters:
  176. /// - fileURL: The `URL` of the file to upload.
  177. /// - url: The `URLConvertible` value.
  178. /// - method: The `HTTPMethod`, `.post` by default.
  179. /// - headers: The `HTTPHeaders`, `nil` by default.
  180. /// - Returns: The created `UploadRequest`.
  181. public static func upload(_ fileURL: URL,
  182. to url: URLConvertible,
  183. method: HTTPMethod = .post,
  184. headers: HTTPHeaders? = nil) -> UploadRequest {
  185. return Session.default.upload(fileURL, to: url, method: method, headers: headers)
  186. }
  187. /// Creates an `UploadRequest` using the `SessionManager.default` to upload the contents of the `fileURL` specificed
  188. /// using the `urlRequest` provided.
  189. ///
  190. /// - Parameters:
  191. /// - fileURL: The `URL` of the file to upload.
  192. /// - urlRequest: The `URLRequestConvertible` value.
  193. /// - Returns: The created `UploadRequest`.
  194. public static func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest {
  195. return Session.default.upload(fileURL, with: urlRequest)
  196. }
  197. // MARK: Data
  198. /// Creates an `UploadRequest` using `SessionManager.default` to upload the contents of the `data` specified using
  199. /// the `url`, `method` and `headers` provided.
  200. ///
  201. /// - Parameters:
  202. /// - data: The `Data` to upload.
  203. /// - url: The `URLConvertible` value.
  204. /// - method: The `HTTPMethod`, `.post` by default.
  205. /// - headers: The `HTTPHeaders`, `nil` by default.
  206. /// - Returns: The created `UploadRequest`.
  207. public static func upload(_ data: Data,
  208. to url: URLConvertible,
  209. method: HTTPMethod = .post,
  210. headers: HTTPHeaders? = nil) -> UploadRequest {
  211. return Session.default.upload(data, to: url, method: method, headers: headers)
  212. }
  213. /// Creates an `UploadRequest` using `SessionManager.default` to upload the contents of the `data` specified using
  214. /// the `urlRequest` provided.
  215. ///
  216. /// - Parameters:
  217. /// - data: The `Data` to upload.
  218. /// - urlRequest: The `URLRequestConvertible` value.
  219. /// - Returns: The created `UploadRequest`.
  220. public static func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest {
  221. return Session.default.upload(data, with: urlRequest)
  222. }
  223. // MARK: InputStream
  224. /// Creates an `UploadRequest` using `SessionManager.default` to upload the content provided by the `stream`
  225. /// specified using the `url`, `method` and `headers` provided.
  226. ///
  227. /// - Parameters:
  228. /// - stream: The `InputStream` to upload.
  229. /// - url: The `URLConvertible` value.
  230. /// - method: The `HTTPMethod`, `.post` by default.
  231. /// - headers: The `HTTPHeaders`, `nil` by default.
  232. /// - Returns: The created `UploadRequest`.
  233. public static func upload(_ stream: InputStream,
  234. to url: URLConvertible,
  235. method: HTTPMethod = .post,
  236. headers: HTTPHeaders? = nil) -> UploadRequest {
  237. return Session.default.upload(stream, to: url, method: method, headers: headers)
  238. }
  239. /// Creates an `UploadRequest` using `SessionManager.default` to upload the content provided by the `stream`
  240. /// specified using the `urlRequest` specified.
  241. ///
  242. /// - Parameters:
  243. /// - stream: The `InputStream` to upload.
  244. /// - urlRequest: The `URLRequestConvertible` value.
  245. /// - Returns: The created `UploadRequest`.
  246. public static func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest {
  247. return Session.default.upload(stream, with: urlRequest)
  248. }
  249. // MARK: MultipartFormData
  250. /// Encodes `multipartFormData` using `encodingMemoryThreshold` and uploads the result using `SessionManager.default`
  251. /// with the `url`, `method`, and `headers` provided.
  252. ///
  253. /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
  254. /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
  255. /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
  256. /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
  257. /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
  258. /// used for larger payloads such as video content.
  259. ///
  260. /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
  261. /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
  262. /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
  263. /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
  264. /// technique was used.
  265. ///
  266. /// - Parameters:
  267. /// - multipartFormData: The closure used to append body parts to the `MultipartFormData`.
  268. /// - encodingMemoryThreshold: The encoding memory threshold in bytes. `10_000_000` bytes by default.
  269. /// - url: The `URLConvertible` value.
  270. /// - method: The `HTTPMethod`, `.post` by default.
  271. /// - headers: The `HTTPHeaders`, `nil` by default.
  272. /// - Returns: The created `UploadRequest`.
  273. public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
  274. usingThreshold encodingMemoryThreshold: UInt64 = MultipartUpload.encodingMemoryThreshold,
  275. to url: URLConvertible,
  276. method: HTTPMethod = .post,
  277. headers: HTTPHeaders? = nil) -> UploadRequest {
  278. return Session.default.upload(multipartFormData: multipartFormData,
  279. usingThreshold: encodingMemoryThreshold,
  280. to: url,
  281. method: method,
  282. headers: headers)
  283. }
  284. /// Encodes `multipartFormData` using `encodingMemoryThreshold` and uploads the result using `SessionManager.default`
  285. /// using the `urlRequest` provided.
  286. ///
  287. /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
  288. /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
  289. /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
  290. /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
  291. /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
  292. /// used for larger payloads such as video content.
  293. ///
  294. /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
  295. /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
  296. /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
  297. /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
  298. /// technique was used.
  299. ///
  300. /// - Parameters:
  301. /// - multipartFormData: The closure used to append body parts to the `MultipartFormData`.
  302. /// - encodingMemoryThreshold: The encoding memory threshold in bytes. `10_000_000` bytes by default.
  303. /// - urlRequest: The `URLRequestConvertible` value.
  304. /// - Returns: The `UploadRequest` created.
  305. @discardableResult
  306. public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
  307. usingThreshold encodingMemoryThreshold: UInt64 = MultipartUpload.encodingMemoryThreshold,
  308. with urlRequest: URLRequestConvertible) -> UploadRequest {
  309. return Session.default.upload(multipartFormData: multipartFormData,
  310. usingThreshold: encodingMemoryThreshold,
  311. with: urlRequest)
  312. }
  313. }