ResponseSerialization.swift 27 KB

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