ResponseSerialization.swift 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  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. import Foundation
  25. // MARK: Protocols
  26. /// The type to which all data response serializers must conform in order to serialize a response.
  27. public protocol DataResponseSerializerProtocol {
  28. /// The type of serialized object to be created by this serializer.
  29. associatedtype SerializedObject
  30. /// The function used to serialize the response data in response handlers.
  31. func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> SerializedObject
  32. }
  33. /// The type to which all download response serializers must conform in order to serialize a response.
  34. public protocol DownloadResponseSerializerProtocol {
  35. /// The type of serialized object to be created by this `DownloadResponseSerializerType`.
  36. associatedtype SerializedObject
  37. /// The function used to serialize the downloaded data in response handlers.
  38. func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> SerializedObject
  39. }
  40. /// A serializer that can handle both data and download responses.
  41. public protocol ResponseSerializer: DataResponseSerializerProtocol & DownloadResponseSerializerProtocol {
  42. var emptyRequestMethods: Set<HTTPMethod> { get }
  43. var emptyResponseCodes: Set<Int> { get }
  44. }
  45. extension ResponseSerializer {
  46. public static var defaultEmptyRequestMethods: Set<HTTPMethod> { return [.head] }
  47. public static var defaultEmptyResponseCodes: Set<Int> { return [204, 205] }
  48. public var emptyRequestMethods: Set<HTTPMethod> { return Self.defaultEmptyRequestMethods }
  49. public var emptyResponseCodes: Set<Int> { return Self.defaultEmptyResponseCodes }
  50. public func requestAllowsEmptyResponseData(_ request: URLRequest?) -> Bool? {
  51. return request.flatMap { $0.httpMethod }
  52. .flatMap(HTTPMethod.init)
  53. .map { emptyRequestMethods.contains($0) }
  54. }
  55. public func responseAllowsEmptyResponseData(_ response: HTTPURLResponse?) -> Bool? {
  56. return response.flatMap { $0.statusCode }
  57. .map { emptyResponseCodes.contains($0) }
  58. }
  59. public func emptyResponseAllowed(forRequest request: URLRequest?, response: HTTPURLResponse?) -> Bool {
  60. return (requestAllowsEmptyResponseData(request) == true) || (responseAllowsEmptyResponseData(response) == true)
  61. }
  62. }
  63. /// By default, any serializer declared to conform to both types will get file serialization for free, as it just feeds
  64. /// the data read from disk into the data response serializer.
  65. public extension DownloadResponseSerializerProtocol where Self: DataResponseSerializerProtocol {
  66. func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> Self.SerializedObject {
  67. guard error == nil else { throw error! }
  68. guard let fileURL = fileURL else {
  69. throw AFError.responseSerializationFailed(reason: .inputFileNil)
  70. }
  71. let data: Data
  72. do {
  73. data = try Data(contentsOf: fileURL)
  74. } catch {
  75. throw AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))
  76. }
  77. do {
  78. return try serialize(request: request, response: response, data: data, error: error)
  79. } catch {
  80. throw error
  81. }
  82. }
  83. }
  84. // MARK: - Default
  85. extension DataRequest {
  86. /// Adds a handler to be called once the request has finished.
  87. ///
  88. /// - Parameters:
  89. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  90. /// - completionHandler: The code to be executed once the request has finished.
  91. /// - Returns: The request.
  92. @discardableResult
  93. public func response(queue: DispatchQueue = .main, completionHandler: @escaping (DataResponse<Data?>) -> Void) -> Self {
  94. appendResponseSerializer {
  95. let result = AFResult(value: self.data, error: self.error)
  96. let response = DataResponse(request: self.request,
  97. response: self.response,
  98. data: self.data,
  99. metrics: self.metrics,
  100. serializationDuration: 0,
  101. result: result)
  102. self.eventMonitor?.request(self, didParseResponse: response)
  103. self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
  104. }
  105. return self
  106. }
  107. /// Adds a handler to be called once the request has finished.
  108. ///
  109. /// - Parameters:
  110. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  111. /// - responseSerializer: The response serializer responsible for serializing the request, response, and data.
  112. /// - completionHandler: The code to be executed once the request has finished.
  113. /// - Returns: The request.
  114. @discardableResult
  115. public func response<Serializer: DataResponseSerializerProtocol>(
  116. queue: DispatchQueue = .main,
  117. responseSerializer: Serializer,
  118. completionHandler: @escaping (DataResponse<Serializer.SerializedObject>) -> Void)
  119. -> Self
  120. {
  121. appendResponseSerializer {
  122. let start = CFAbsoluteTimeGetCurrent()
  123. let result = AFResult { try responseSerializer.serialize(request: self.request,
  124. response: self.response,
  125. data: self.data,
  126. error: self.error) }
  127. let end = CFAbsoluteTimeGetCurrent()
  128. let response = DataResponse(request: self.request,
  129. response: self.response,
  130. data: self.data,
  131. metrics: self.metrics,
  132. serializationDuration: (end - start),
  133. result: result)
  134. self.eventMonitor?.request(self, didParseResponse: response)
  135. guard let serializerError = result.error, let delegate = self.delegate else {
  136. self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
  137. return
  138. }
  139. delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
  140. var didComplete: (() -> Void)?
  141. defer {
  142. if let didComplete = didComplete {
  143. self.responseSerializerDidComplete { queue.async { didComplete() } }
  144. }
  145. }
  146. switch retryResult {
  147. case .doNotRetry:
  148. didComplete = { completionHandler(response) }
  149. case .doNotRetryWithError(let retryError):
  150. let result = AFResult<Serializer.SerializedObject>.failure(retryError)
  151. let response = DataResponse(request: self.request,
  152. response: self.response,
  153. data: self.data,
  154. metrics: self.metrics,
  155. serializationDuration: (end - start),
  156. result: result)
  157. didComplete = { completionHandler(response) }
  158. case .retry, .retryWithDelay:
  159. delegate.retryRequest(self, withDelay: retryResult.delay)
  160. }
  161. }
  162. }
  163. return self
  164. }
  165. }
  166. extension DownloadRequest {
  167. /// Adds a handler to be called once the request has finished.
  168. ///
  169. /// - Parameters:
  170. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  171. /// - completionHandler: The code to be executed once the request has finished.
  172. /// - Returns: The request.
  173. @discardableResult
  174. public func response(
  175. queue: DispatchQueue = .main,
  176. completionHandler: @escaping (DownloadResponse<URL?>) -> Void)
  177. -> Self
  178. {
  179. appendResponseSerializer {
  180. let result = AFResult(value: self.fileURL , error: self.error)
  181. let response = DownloadResponse(request: self.request,
  182. response: self.response,
  183. fileURL: self.fileURL,
  184. resumeData: self.resumeData,
  185. metrics: self.metrics,
  186. serializationDuration: 0,
  187. result: result)
  188. self.eventMonitor?.request(self, didParseResponse: response)
  189. self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
  190. }
  191. return self
  192. }
  193. /// Adds a handler to be called once the request has finished.
  194. ///
  195. /// - Parameters:
  196. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  197. /// - responseSerializer: The response serializer responsible for serializing the request, response, and data
  198. /// contained in the destination url.
  199. /// - completionHandler: The code to be executed once the request has finished.
  200. /// - Returns: The request.
  201. @discardableResult
  202. public func response<T: DownloadResponseSerializerProtocol>(
  203. queue: DispatchQueue = .main,
  204. responseSerializer: T,
  205. completionHandler: @escaping (DownloadResponse<T.SerializedObject>) -> Void)
  206. -> Self
  207. {
  208. appendResponseSerializer {
  209. let start = CFAbsoluteTimeGetCurrent()
  210. let result = AFResult { try responseSerializer.serializeDownload(request: self.request,
  211. response: self.response,
  212. fileURL: self.fileURL,
  213. error: self.error) }
  214. let end = CFAbsoluteTimeGetCurrent()
  215. let response = DownloadResponse(request: self.request,
  216. response: self.response,
  217. fileURL: self.fileURL,
  218. resumeData: self.resumeData,
  219. metrics: self.metrics,
  220. serializationDuration: (end - start),
  221. result: result)
  222. self.eventMonitor?.request(self, didParseResponse: response)
  223. guard let serializerError = result.error, let delegate = self.delegate else {
  224. self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
  225. return
  226. }
  227. delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
  228. var didComplete: (() -> Void)?
  229. defer {
  230. if let didComplete = didComplete {
  231. self.responseSerializerDidComplete { queue.async { didComplete() } }
  232. }
  233. }
  234. switch retryResult {
  235. case .doNotRetry:
  236. didComplete = { completionHandler(response) }
  237. case .doNotRetryWithError(let retryError):
  238. let result = AFResult<T.SerializedObject>.failure(retryError)
  239. let response = DownloadResponse(request: self.request,
  240. response: self.response,
  241. fileURL: self.fileURL,
  242. resumeData: self.resumeData,
  243. metrics: self.metrics,
  244. serializationDuration: (end - start),
  245. result: result)
  246. didComplete = { completionHandler(response) }
  247. case .retry, .retryWithDelay:
  248. delegate.retryRequest(self, withDelay: retryResult.delay)
  249. }
  250. }
  251. }
  252. return self
  253. }
  254. }
  255. // MARK: - Data
  256. extension DataRequest {
  257. /// Adds a handler to be called once the request has finished.
  258. ///
  259. /// - Parameters:
  260. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  261. /// - completionHandler: The code to be executed once the request has finished.
  262. /// - Returns: The request.
  263. @discardableResult
  264. public func responseData(
  265. queue: DispatchQueue = .main,
  266. completionHandler: @escaping (DataResponse<Data>) -> Void)
  267. -> Self
  268. {
  269. return response(queue: queue,
  270. responseSerializer: DataResponseSerializer(),
  271. completionHandler: completionHandler)
  272. }
  273. }
  274. /// A `ResponseSerializer` that performs minimal reponse checking and returns any response data as-is. By default, a
  275. /// request returning `nil` or no data is considered an error. However, if the response is has a status code valid for
  276. /// empty responses (`204`, `205`), then an empty `Data` value is returned.
  277. public final class DataResponseSerializer: ResponseSerializer {
  278. /// HTTP response codes for which empty responses are allowed.
  279. public let emptyResponseCodes: Set<Int>
  280. /// HTTP request methods for which empty responses are allowed.
  281. public let emptyRequestMethods: Set<HTTPMethod>
  282. /// Creates an instance using the provided values.
  283. ///
  284. /// - Parameters:
  285. /// - emptyResponseCodes: The HTTP response codes for which empty responses are allowed. Defaults to
  286. /// `[204, 205]`.
  287. /// - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. Defaults to `[.head]`.
  288. public init(emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
  289. emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) {
  290. self.emptyResponseCodes = emptyResponseCodes
  291. self.emptyRequestMethods = emptyRequestMethods
  292. }
  293. public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Data {
  294. guard error == nil else { throw error! }
  295. guard let data = data, !data.isEmpty else {
  296. guard emptyResponseAllowed(forRequest: request, response: response) else {
  297. throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
  298. }
  299. return Data()
  300. }
  301. return data
  302. }
  303. }
  304. extension DownloadRequest {
  305. /// Adds a handler to be called once the request has finished.
  306. ///
  307. /// - Parameters:
  308. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  309. /// - completionHandler: The code to be executed once the request has finished.
  310. /// - Returns: The request.
  311. @discardableResult
  312. public func responseData(
  313. queue: DispatchQueue = .main,
  314. completionHandler: @escaping (DownloadResponse<Data>) -> Void)
  315. -> Self
  316. {
  317. return response(
  318. queue: queue,
  319. responseSerializer: DataResponseSerializer(),
  320. completionHandler: completionHandler
  321. )
  322. }
  323. }
  324. // MARK: - String
  325. /// A `ResponseSerializer` that decodes the response data as a `String`. By default, a request returning `nil` or no
  326. /// data is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`),
  327. /// then an empty `String` is returned.
  328. public final class StringResponseSerializer: ResponseSerializer {
  329. /// Optional string encoding used to validate the response.
  330. public let encoding: String.Encoding?
  331. /// HTTP response codes for which empty responses are allowed.
  332. public let emptyResponseCodes: Set<Int>
  333. /// HTTP request methods for which empty responses are allowed.
  334. public let emptyRequestMethods: Set<HTTPMethod>
  335. /// Creates an instance with the provided values.
  336. ///
  337. /// - Parameters:
  338. /// - encoding: A string encoding. Defaults to `nil`, in which case the encoding will be determined
  339. /// from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
  340. /// - emptyResponseCodes: The HTTP response codes for which empty responses are allowed. Defaults to
  341. /// `[204, 205]`.
  342. /// - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. Defaults to `[.head]`.
  343. public init(encoding: String.Encoding? = nil,
  344. emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
  345. emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) {
  346. self.encoding = encoding
  347. self.emptyResponseCodes = emptyResponseCodes
  348. self.emptyRequestMethods = emptyRequestMethods
  349. }
  350. public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> String {
  351. guard error == nil else { throw error! }
  352. guard let data = data, !data.isEmpty else {
  353. guard emptyResponseAllowed(forRequest: request, response: response) else {
  354. throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
  355. }
  356. return ""
  357. }
  358. var convertedEncoding = encoding
  359. if let encodingName = response?.textEncodingName as CFString?, convertedEncoding == nil {
  360. let ianaCharSet = CFStringConvertIANACharSetNameToEncoding(encodingName)
  361. let nsStringEncoding = CFStringConvertEncodingToNSStringEncoding(ianaCharSet)
  362. convertedEncoding = String.Encoding(rawValue: nsStringEncoding)
  363. }
  364. let actualEncoding = convertedEncoding ?? .isoLatin1
  365. guard let string = String(data: data, encoding: actualEncoding) else {
  366. throw AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding))
  367. }
  368. return string
  369. }
  370. }
  371. extension DataRequest {
  372. /// Adds a handler to be called once the request has finished.
  373. ///
  374. /// - Parameters:
  375. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  376. /// - encoding: The string encoding. Defaults to `nil`, in which case the encoding will be determined from
  377. /// the server response, falling back to the default HTTP character set, `ISO-8859-1`.
  378. /// - completionHandler: A closure to be executed once the request has finished.
  379. /// - Returns: The request.
  380. @discardableResult
  381. public func responseString(queue: DispatchQueue = .main,
  382. encoding: String.Encoding? = nil,
  383. completionHandler: @escaping (DataResponse<String>) -> Void) -> Self {
  384. return response(queue: queue,
  385. responseSerializer: StringResponseSerializer(encoding: encoding),
  386. completionHandler: completionHandler)
  387. }
  388. }
  389. extension DownloadRequest {
  390. /// Adds a handler to be called once the request has finished.
  391. ///
  392. /// - Parameters:
  393. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  394. /// - encoding: The string encoding. Defaults to `nil`, in which case the encoding will be determined from
  395. /// the server response, falling back to the default HTTP character set, `ISO-8859-1`.
  396. /// - completionHandler: A closure to be executed once the request has finished.
  397. /// - Returns: The request.
  398. @discardableResult
  399. public func responseString(
  400. queue: DispatchQueue = .main,
  401. encoding: String.Encoding? = nil,
  402. completionHandler: @escaping (DownloadResponse<String>) -> Void)
  403. -> Self
  404. {
  405. return response(
  406. queue: queue,
  407. responseSerializer: StringResponseSerializer(encoding: encoding),
  408. completionHandler: completionHandler
  409. )
  410. }
  411. }
  412. // MARK: - JSON
  413. /// A `ResponseSerializer` that decodes the response data using `JSONSerialization`. By default, a request returning
  414. /// `nil` or no data is considered an error. However, if the response is has a status code valid for empty responses
  415. /// (`204`, `205`), then an `NSNull` value is returned.
  416. public final class JSONResponseSerializer: ResponseSerializer {
  417. /// `JSONSerialization.ReadingOptions` used when serializing a response.
  418. public let options: JSONSerialization.ReadingOptions
  419. /// HTTP response codes for which empty responses are allowed.
  420. public let emptyResponseCodes: Set<Int>
  421. /// HTTP request methods for which empty responses are allowed.
  422. public let emptyRequestMethods: Set<HTTPMethod>
  423. /// Creates an instance with the provided values.
  424. ///
  425. /// - Parameters:
  426. /// - options: The options to use. Defaults to `.allowFragments`.
  427. /// - emptyResponseCodes: The HTTP response codes for which empty responses are allowed. Defaults to
  428. /// `[204, 205]`.
  429. /// - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. Defaults to `[.head]`.
  430. public init(options: JSONSerialization.ReadingOptions = .allowFragments,
  431. emptyResponseCodes: Set<Int> = JSONResponseSerializer.defaultEmptyResponseCodes,
  432. emptyRequestMethods: Set<HTTPMethod> = JSONResponseSerializer.defaultEmptyRequestMethods) {
  433. self.options = options
  434. self.emptyResponseCodes = emptyResponseCodes
  435. self.emptyRequestMethods = emptyRequestMethods
  436. }
  437. public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Any {
  438. guard error == nil else { throw error! }
  439. guard let data = data, !data.isEmpty else {
  440. guard emptyResponseAllowed(forRequest: request, response: response) else {
  441. throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
  442. }
  443. return NSNull()
  444. }
  445. do {
  446. return try JSONSerialization.jsonObject(with: data, options: options)
  447. } catch {
  448. throw AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error))
  449. }
  450. }
  451. }
  452. extension DataRequest {
  453. /// Adds a handler to be called once the request has finished.
  454. ///
  455. /// - Parameters:
  456. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  457. /// - options: The JSON serialization reading options. Defaults to `.allowFragments`.
  458. /// - completionHandler: A closure to be executed once the request has finished.
  459. /// - Returns: The request.
  460. @discardableResult
  461. public func responseJSON(queue: DispatchQueue = .main,
  462. options: JSONSerialization.ReadingOptions = .allowFragments,
  463. completionHandler: @escaping (DataResponse<Any>) -> Void) -> Self {
  464. return response(queue: queue,
  465. responseSerializer: JSONResponseSerializer(options: options),
  466. completionHandler: completionHandler)
  467. }
  468. }
  469. extension DownloadRequest {
  470. /// Adds a handler to be called once the request has finished.
  471. ///
  472. /// - Parameters:
  473. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  474. /// - options: The JSON serialization reading options. Defaults to `.allowFragments`.
  475. /// - completionHandler: A closure to be executed once the request has finished.
  476. /// - Returns: The request.
  477. @discardableResult
  478. public func responseJSON(
  479. queue: DispatchQueue = .main,
  480. options: JSONSerialization.ReadingOptions = .allowFragments,
  481. completionHandler: @escaping (DownloadResponse<Any>) -> Void)
  482. -> Self
  483. {
  484. return response(queue: queue,
  485. responseSerializer: JSONResponseSerializer(options: options),
  486. completionHandler: completionHandler)
  487. }
  488. }
  489. // MARK: - Empty
  490. /// A protocol for a type representing an empty response. Use `T.emptyValue` to get an instance.
  491. public protocol EmptyResponse {
  492. static func emptyValue() -> Self
  493. }
  494. /// A type representing an empty response. Use `Empty.value` to get the instance.
  495. public struct Empty: Decodable {
  496. public static let value = Empty()
  497. }
  498. extension Empty: EmptyResponse {
  499. public static func emptyValue() -> Empty {
  500. return value
  501. }
  502. }
  503. // MARK: - DataDecoder Protocol
  504. /// Any type which can decode `Data`.
  505. public protocol DataDecoder {
  506. /// Decode `Data` into the provided type.
  507. ///
  508. /// - Parameters:
  509. /// - type: The `Type` to be decoded.
  510. /// - data: The `Data`
  511. /// - Returns: The decoded value of type `D`.
  512. /// - Throws: Any error that occurs during decode.
  513. func decode<D: Decodable>(_ type: D.Type, from data: Data) throws -> D
  514. }
  515. /// `JSONDecoder` automatically conforms to `DataDecoder`.
  516. extension JSONDecoder: DataDecoder { }
  517. // MARK: - Decodable
  518. /// A `ResponseSerializer` that decodes the response data as a generic value using any type that conforms to
  519. /// `DataDecoder`. By default, this is an instance of `JSONDecoder`. Additionally, a request returning `nil` or no data
  520. /// is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`), then
  521. /// the `Empty.value` value is returned.
  522. public final class DecodableResponseSerializer<T: Decodable>: ResponseSerializer {
  523. /// The `JSONDecoder` instance used to decode responses.
  524. public let decoder: DataDecoder
  525. /// HTTP response codes for which empty responses are allowed.
  526. public let emptyResponseCodes: Set<Int>
  527. /// HTTP request methods for which empty responses are allowed.
  528. public let emptyRequestMethods: Set<HTTPMethod>
  529. /// Creates an instance using the values provided.
  530. ///
  531. /// - Parameters:
  532. /// - decoder: The `JSONDecoder`. Defaults to a `JSONDecoder()`.
  533. /// - emptyResponseCodes: The HTTP response codes for which empty responses are allowed. Defaults to
  534. /// `[204, 205]`.
  535. /// - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. Defaults to `[.head]`.
  536. public init(decoder: DataDecoder = JSONDecoder(),
  537. emptyResponseCodes: Set<Int> = DecodableResponseSerializer.defaultEmptyResponseCodes,
  538. emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer.defaultEmptyRequestMethods) {
  539. self.decoder = decoder
  540. self.emptyResponseCodes = emptyResponseCodes
  541. self.emptyRequestMethods = emptyRequestMethods
  542. }
  543. public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> T {
  544. guard error == nil else { throw error! }
  545. guard let data = data, !data.isEmpty else {
  546. guard emptyResponseAllowed(forRequest: request, response: response) else {
  547. throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
  548. }
  549. guard let emptyResponseType = T.self as? EmptyResponse.Type, let emptyValue = emptyResponseType.emptyValue() as? T else {
  550. throw AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "\(T.self)"))
  551. }
  552. return emptyValue
  553. }
  554. do {
  555. return try decoder.decode(T.self, from: data)
  556. } catch {
  557. throw AFError.responseSerializationFailed(reason: .decodingFailed(error: error))
  558. }
  559. }
  560. }
  561. extension DataRequest {
  562. /// Adds a handler to be called once the request has finished.
  563. ///
  564. /// - Parameters:
  565. /// - queue: The queue on which the completion handler is dispatched. Defaults to `.main`.
  566. /// - decoder: The `DataDecoder` to use to decode the response. Defaults to a `JSONDecoder` with default
  567. /// settings.
  568. /// - completionHandler: A closure to be executed once the request has finished.
  569. /// - Returns: The request.
  570. @discardableResult
  571. public func responseDecodable<T: Decodable>(queue: DispatchQueue = .main,
  572. decoder: DataDecoder = JSONDecoder(),
  573. completionHandler: @escaping (DataResponse<T>) -> Void) -> Self {
  574. return response(queue: queue,
  575. responseSerializer: DecodableResponseSerializer(decoder: decoder),
  576. completionHandler: completionHandler)
  577. }
  578. }