Added Android code
[wl-app.git] / iOS / Pods / Alamofire / Source / ResponseSerialization.swift
1 //
2 //  ResponseSerialization.swift
3 //
4 //  Copyright (c) 2014-2017 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 /// The type in which all data response serializers must conform to in order to serialize a response.
28 public protocol DataResponseSerializerProtocol {
29     /// The type of serialized object to be created by this `DataResponseSerializerType`.
30     associatedtype SerializedObject
31
32     /// A closure used by response handlers that takes a request, response, data and error and returns a result.
33     var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<SerializedObject> { get }
34 }
35
36 // MARK: -
37
38 /// A generic `DataResponseSerializerType` used to serialize a request, response, and data into a serialized object.
39 public struct DataResponseSerializer<Value>: DataResponseSerializerProtocol {
40     /// The type of serialized object to be created by this `DataResponseSerializer`.
41     public typealias SerializedObject = Value
42
43     /// A closure used by response handlers that takes a request, response, data and error and returns a result.
44     public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>
45
46     /// Initializes the `ResponseSerializer` instance with the given serialize response closure.
47     ///
48     /// - parameter serializeResponse: The closure used to serialize the response.
49     ///
50     /// - returns: The new generic response serializer instance.
51     public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>) {
52         self.serializeResponse = serializeResponse
53     }
54 }
55
56 // MARK: -
57
58 /// The type in which all download response serializers must conform to in order to serialize a response.
59 public protocol DownloadResponseSerializerProtocol {
60     /// The type of serialized object to be created by this `DownloadResponseSerializerType`.
61     associatedtype SerializedObject
62
63     /// A closure used by response handlers that takes a request, response, url and error and returns a result.
64     var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<SerializedObject> { get }
65 }
66
67 // MARK: -
68
69 /// A generic `DownloadResponseSerializerType` used to serialize a request, response, and data into a serialized object.
70 public struct DownloadResponseSerializer<Value>: DownloadResponseSerializerProtocol {
71     /// The type of serialized object to be created by this `DownloadResponseSerializer`.
72     public typealias SerializedObject = Value
73
74     /// A closure used by response handlers that takes a request, response, url and error and returns a result.
75     public var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>
76
77     /// Initializes the `ResponseSerializer` instance with the given serialize response closure.
78     ///
79     /// - parameter serializeResponse: The closure used to serialize the response.
80     ///
81     /// - returns: The new generic response serializer instance.
82     public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>) {
83         self.serializeResponse = serializeResponse
84     }
85 }
86
87 // MARK: - Timeline
88
89 extension Request {
90     var timeline: Timeline {
91         let requestStartTime = self.startTime ?? CFAbsoluteTimeGetCurrent()
92         let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
93         let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
94
95         return Timeline(
96             requestStartTime: requestStartTime,
97             initialResponseTime: initialResponseTime,
98             requestCompletedTime: requestCompletedTime,
99             serializationCompletedTime: CFAbsoluteTimeGetCurrent()
100         )
101     }
102 }
103
104 // MARK: - Default
105
106 extension DataRequest {
107     /// Adds a handler to be called once the request has finished.
108     ///
109     /// - parameter queue:             The queue on which the completion handler is dispatched.
110     /// - parameter completionHandler: The code to be executed once the request has finished.
111     ///
112     /// - returns: The request.
113     @discardableResult
114     public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
115         delegate.queue.addOperation {
116             (queue ?? DispatchQueue.main).async {
117                 var dataResponse = DefaultDataResponse(
118                     request: self.request,
119                     response: self.response,
120                     data: self.delegate.data,
121                     error: self.delegate.error,
122                     timeline: self.timeline
123                 )
124
125                 dataResponse.add(self.delegate.metrics)
126
127                 completionHandler(dataResponse)
128             }
129         }
130
131         return self
132     }
133
134     /// Adds a handler to be called once the request has finished.
135     ///
136     /// - parameter queue:              The queue on which the completion handler is dispatched.
137     /// - parameter responseSerializer: The response serializer responsible for serializing the request, response,
138     ///                                 and data.
139     /// - parameter completionHandler:  The code to be executed once the request has finished.
140     ///
141     /// - returns: The request.
142     @discardableResult
143     public func response<T: DataResponseSerializerProtocol>(
144         queue: DispatchQueue? = nil,
145         responseSerializer: T,
146         completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
147         -> Self
148     {
149         delegate.queue.addOperation {
150             let result = responseSerializer.serializeResponse(
151                 self.request,
152                 self.response,
153                 self.delegate.data,
154                 self.delegate.error
155             )
156
157             var dataResponse = DataResponse<T.SerializedObject>(
158                 request: self.request,
159                 response: self.response,
160                 data: self.delegate.data,
161                 result: result,
162                 timeline: self.timeline
163             )
164
165             dataResponse.add(self.delegate.metrics)
166
167             (queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
168         }
169
170         return self
171     }
172 }
173
174 extension DownloadRequest {
175     /// Adds a handler to be called once the request has finished.
176     ///
177     /// - parameter queue:             The queue on which the completion handler is dispatched.
178     /// - parameter completionHandler: The code to be executed once the request has finished.
179     ///
180     /// - returns: The request.
181     @discardableResult
182     public func response(
183         queue: DispatchQueue? = nil,
184         completionHandler: @escaping (DefaultDownloadResponse) -> Void)
185         -> Self
186     {
187         delegate.queue.addOperation {
188             (queue ?? DispatchQueue.main).async {
189                 var downloadResponse = DefaultDownloadResponse(
190                     request: self.request,
191                     response: self.response,
192                     temporaryURL: self.downloadDelegate.temporaryURL,
193                     destinationURL: self.downloadDelegate.destinationURL,
194                     resumeData: self.downloadDelegate.resumeData,
195                     error: self.downloadDelegate.error,
196                     timeline: self.timeline
197                 )
198
199                 downloadResponse.add(self.delegate.metrics)
200
201                 completionHandler(downloadResponse)
202             }
203         }
204
205         return self
206     }
207
208     /// Adds a handler to be called once the request has finished.
209     ///
210     /// - parameter queue:              The queue on which the completion handler is dispatched.
211     /// - parameter responseSerializer: The response serializer responsible for serializing the request, response,
212     ///                                 and data contained in the destination url.
213     /// - parameter completionHandler:  The code to be executed once the request has finished.
214     ///
215     /// - returns: The request.
216     @discardableResult
217     public func response<T: DownloadResponseSerializerProtocol>(
218         queue: DispatchQueue? = nil,
219         responseSerializer: T,
220         completionHandler: @escaping (DownloadResponse<T.SerializedObject>) -> Void)
221         -> Self
222     {
223         delegate.queue.addOperation {
224             let result = responseSerializer.serializeResponse(
225                 self.request,
226                 self.response,
227                 self.downloadDelegate.fileURL,
228                 self.downloadDelegate.error
229             )
230
231             var downloadResponse = DownloadResponse<T.SerializedObject>(
232                 request: self.request,
233                 response: self.response,
234                 temporaryURL: self.downloadDelegate.temporaryURL,
235                 destinationURL: self.downloadDelegate.destinationURL,
236                 resumeData: self.downloadDelegate.resumeData,
237                 result: result,
238                 timeline: self.timeline
239             )
240
241             downloadResponse.add(self.delegate.metrics)
242
243             (queue ?? DispatchQueue.main).async { completionHandler(downloadResponse) }
244         }
245
246         return self
247     }
248 }
249
250 // MARK: - Data
251
252 extension Request {
253     /// Returns a result data type that contains the response data as-is.
254     ///
255     /// - parameter response: The response from the server.
256     /// - parameter data:     The data returned from the server.
257     /// - parameter error:    The error already encountered if it exists.
258     ///
259     /// - returns: The result data type.
260     public static func serializeResponseData(response: HTTPURLResponse?, data: Data?, error: Error?) -> Result<Data> {
261         guard error == nil else { return .failure(error!) }
262
263         if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(Data()) }
264
265         guard let validData = data else {
266             return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
267         }
268
269         return .success(validData)
270     }
271 }
272
273 extension DataRequest {
274     /// Creates a response serializer that returns the associated data as-is.
275     ///
276     /// - returns: A data response serializer.
277     public static func dataResponseSerializer() -> DataResponseSerializer<Data> {
278         return DataResponseSerializer { _, response, data, error in
279             return Request.serializeResponseData(response: response, data: data, error: error)
280         }
281     }
282
283     /// Adds a handler to be called once the request has finished.
284     ///
285     /// - parameter completionHandler: The code to be executed once the request has finished.
286     ///
287     /// - returns: The request.
288     @discardableResult
289     public func responseData(
290         queue: DispatchQueue? = nil,
291         completionHandler: @escaping (DataResponse<Data>) -> Void)
292         -> Self
293     {
294         return response(
295             queue: queue,
296             responseSerializer: DataRequest.dataResponseSerializer(),
297             completionHandler: completionHandler
298         )
299     }
300 }
301
302 extension DownloadRequest {
303     /// Creates a response serializer that returns the associated data as-is.
304     ///
305     /// - returns: A data response serializer.
306     public static func dataResponseSerializer() -> DownloadResponseSerializer<Data> {
307         return DownloadResponseSerializer { _, response, fileURL, error in
308             guard error == nil else { return .failure(error!) }
309
310             guard let fileURL = fileURL else {
311                 return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
312             }
313
314             do {
315                 let data = try Data(contentsOf: fileURL)
316                 return Request.serializeResponseData(response: response, data: data, error: error)
317             } catch {
318                 return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
319             }
320         }
321     }
322
323     /// Adds a handler to be called once the request has finished.
324     ///
325     /// - parameter completionHandler: The code to be executed once the request has finished.
326     ///
327     /// - returns: The request.
328     @discardableResult
329     public func responseData(
330         queue: DispatchQueue? = nil,
331         completionHandler: @escaping (DownloadResponse<Data>) -> Void)
332         -> Self
333     {
334         return response(
335             queue: queue,
336             responseSerializer: DownloadRequest.dataResponseSerializer(),
337             completionHandler: completionHandler
338         )
339     }
340 }
341
342 // MARK: - String
343
344 extension Request {
345     /// Returns a result string type initialized from the response data with the specified string encoding.
346     ///
347     /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
348     ///                       response, falling back to the default HTTP default character set, ISO-8859-1.
349     /// - parameter response: The response from the server.
350     /// - parameter data:     The data returned from the server.
351     /// - parameter error:    The error already encountered if it exists.
352     ///
353     /// - returns: The result data type.
354     public static func serializeResponseString(
355         encoding: String.Encoding?,
356         response: HTTPURLResponse?,
357         data: Data?,
358         error: Error?)
359         -> Result<String>
360     {
361         guard error == nil else { return .failure(error!) }
362
363         if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success("") }
364
365         guard let validData = data else {
366             return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
367         }
368
369         var convertedEncoding = encoding
370
371         if let encodingName = response?.textEncodingName as CFString!, convertedEncoding == nil {
372             convertedEncoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(
373                 CFStringConvertIANACharSetNameToEncoding(encodingName))
374             )
375         }
376
377         let actualEncoding = convertedEncoding ?? String.Encoding.isoLatin1
378
379         if let string = String(data: validData, encoding: actualEncoding) {
380             return .success(string)
381         } else {
382             return .failure(AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding)))
383         }
384     }
385 }
386
387 extension DataRequest {
388     /// Creates a response serializer that returns a result string type initialized from the response data with
389     /// the specified string encoding.
390     ///
391     /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
392     ///                       response, falling back to the default HTTP default character set, ISO-8859-1.
393     ///
394     /// - returns: A string response serializer.
395     public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DataResponseSerializer<String> {
396         return DataResponseSerializer { _, response, data, error in
397             return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
398         }
399     }
400
401     /// Adds a handler to be called once the request has finished.
402     ///
403     /// - parameter encoding:          The string encoding. If `nil`, the string encoding will be determined from the
404     ///                                server response, falling back to the default HTTP default character set,
405     ///                                ISO-8859-1.
406     /// - parameter completionHandler: A closure to be executed once the request has finished.
407     ///
408     /// - returns: The request.
409     @discardableResult
410     public func responseString(
411         queue: DispatchQueue? = nil,
412         encoding: String.Encoding? = nil,
413         completionHandler: @escaping (DataResponse<String>) -> Void)
414         -> Self
415     {
416         return response(
417             queue: queue,
418             responseSerializer: DataRequest.stringResponseSerializer(encoding: encoding),
419             completionHandler: completionHandler
420         )
421     }
422 }
423
424 extension DownloadRequest {
425     /// Creates a response serializer that returns a result string type initialized from the response data with
426     /// the specified string encoding.
427     ///
428     /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
429     ///                       response, falling back to the default HTTP default character set, ISO-8859-1.
430     ///
431     /// - returns: A string response serializer.
432     public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DownloadResponseSerializer<String> {
433         return DownloadResponseSerializer { _, response, fileURL, error in
434             guard error == nil else { return .failure(error!) }
435
436             guard let fileURL = fileURL else {
437                 return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
438             }
439
440             do {
441                 let data = try Data(contentsOf: fileURL)
442                 return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
443             } catch {
444                 return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
445             }
446         }
447     }
448
449     /// Adds a handler to be called once the request has finished.
450     ///
451     /// - parameter encoding:          The string encoding. If `nil`, the string encoding will be determined from the
452     ///                                server response, falling back to the default HTTP default character set,
453     ///                                ISO-8859-1.
454     /// - parameter completionHandler: A closure to be executed once the request has finished.
455     ///
456     /// - returns: The request.
457     @discardableResult
458     public func responseString(
459         queue: DispatchQueue? = nil,
460         encoding: String.Encoding? = nil,
461         completionHandler: @escaping (DownloadResponse<String>) -> Void)
462         -> Self
463     {
464         return response(
465             queue: queue,
466             responseSerializer: DownloadRequest.stringResponseSerializer(encoding: encoding),
467             completionHandler: completionHandler
468         )
469     }
470 }
471
472 // MARK: - JSON
473
474 extension Request {
475     /// Returns a JSON object contained in a result type constructed from the response data using `JSONSerialization`
476     /// with the specified reading options.
477     ///
478     /// - parameter options:  The JSON serialization reading options. Defaults to `.allowFragments`.
479     /// - parameter response: The response from the server.
480     /// - parameter data:     The data returned from the server.
481     /// - parameter error:    The error already encountered if it exists.
482     ///
483     /// - returns: The result data type.
484     public static func serializeResponseJSON(
485         options: JSONSerialization.ReadingOptions,
486         response: HTTPURLResponse?,
487         data: Data?,
488         error: Error?)
489         -> Result<Any>
490     {
491         guard error == nil else { return .failure(error!) }
492
493         if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
494
495         guard let validData = data, validData.count > 0 else {
496             return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
497         }
498
499         do {
500             let json = try JSONSerialization.jsonObject(with: validData, options: options)
501             return .success(json)
502         } catch {
503             return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
504         }
505     }
506 }
507
508 extension DataRequest {
509     /// Creates a response serializer that returns a JSON object result type constructed from the response data using
510     /// `JSONSerialization` with the specified reading options.
511     ///
512     /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
513     ///
514     /// - returns: A JSON object response serializer.
515     public static func jsonResponseSerializer(
516         options: JSONSerialization.ReadingOptions = .allowFragments)
517         -> DataResponseSerializer<Any>
518     {
519         return DataResponseSerializer { _, response, data, error in
520             return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
521         }
522     }
523
524     /// Adds a handler to be called once the request has finished.
525     ///
526     /// - parameter options:           The JSON serialization reading options. Defaults to `.allowFragments`.
527     /// - parameter completionHandler: A closure to be executed once the request has finished.
528     ///
529     /// - returns: The request.
530     @discardableResult
531     public func responseJSON(
532         queue: DispatchQueue? = nil,
533         options: JSONSerialization.ReadingOptions = .allowFragments,
534         completionHandler: @escaping (DataResponse<Any>) -> Void)
535         -> Self
536     {
537         return response(
538             queue: queue,
539             responseSerializer: DataRequest.jsonResponseSerializer(options: options),
540             completionHandler: completionHandler
541         )
542     }
543 }
544
545 extension DownloadRequest {
546     /// Creates a response serializer that returns a JSON object result type constructed from the response data using
547     /// `JSONSerialization` with the specified reading options.
548     ///
549     /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
550     ///
551     /// - returns: A JSON object response serializer.
552     public static func jsonResponseSerializer(
553         options: JSONSerialization.ReadingOptions = .allowFragments)
554         -> DownloadResponseSerializer<Any>
555     {
556         return DownloadResponseSerializer { _, response, fileURL, error in
557             guard error == nil else { return .failure(error!) }
558
559             guard let fileURL = fileURL else {
560                 return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
561             }
562
563             do {
564                 let data = try Data(contentsOf: fileURL)
565                 return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
566             } catch {
567                 return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
568             }
569         }
570     }
571
572     /// Adds a handler to be called once the request has finished.
573     ///
574     /// - parameter options:           The JSON serialization reading options. Defaults to `.allowFragments`.
575     /// - parameter completionHandler: A closure to be executed once the request has finished.
576     ///
577     /// - returns: The request.
578     @discardableResult
579     public func responseJSON(
580         queue: DispatchQueue? = nil,
581         options: JSONSerialization.ReadingOptions = .allowFragments,
582         completionHandler: @escaping (DownloadResponse<Any>) -> Void)
583         -> Self
584     {
585         return response(
586             queue: queue,
587             responseSerializer: DownloadRequest.jsonResponseSerializer(options: options),
588             completionHandler: completionHandler
589         )
590     }
591 }
592
593 // MARK: - Property List
594
595 extension Request {
596     /// Returns a plist object contained in a result type constructed from the response data using
597     /// `PropertyListSerialization` with the specified reading options.
598     ///
599     /// - parameter options:  The property list reading options. Defaults to `[]`.
600     /// - parameter response: The response from the server.
601     /// - parameter data:     The data returned from the server.
602     /// - parameter error:    The error already encountered if it exists.
603     ///
604     /// - returns: The result data type.
605     public static func serializeResponsePropertyList(
606         options: PropertyListSerialization.ReadOptions,
607         response: HTTPURLResponse?,
608         data: Data?,
609         error: Error?)
610         -> Result<Any>
611     {
612         guard error == nil else { return .failure(error!) }
613
614         if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
615
616         guard let validData = data, validData.count > 0 else {
617             return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
618         }
619
620         do {
621             let plist = try PropertyListSerialization.propertyList(from: validData, options: options, format: nil)
622             return .success(plist)
623         } catch {
624             return .failure(AFError.responseSerializationFailed(reason: .propertyListSerializationFailed(error: error)))
625         }
626     }
627 }
628
629 extension DataRequest {
630     /// Creates a response serializer that returns an object constructed from the response data using
631     /// `PropertyListSerialization` with the specified reading options.
632     ///
633     /// - parameter options: The property list reading options. Defaults to `[]`.
634     ///
635     /// - returns: A property list object response serializer.
636     public static func propertyListResponseSerializer(
637         options: PropertyListSerialization.ReadOptions = [])
638         -> DataResponseSerializer<Any>
639     {
640         return DataResponseSerializer { _, response, data, error in
641             return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error)
642         }
643     }
644
645     /// Adds a handler to be called once the request has finished.
646     ///
647     /// - parameter options:           The property list reading options. Defaults to `[]`.
648     /// - parameter completionHandler: A closure to be executed once the request has finished.
649     ///
650     /// - returns: The request.
651     @discardableResult
652     public func responsePropertyList(
653         queue: DispatchQueue? = nil,
654         options: PropertyListSerialization.ReadOptions = [],
655         completionHandler: @escaping (DataResponse<Any>) -> Void)
656         -> Self
657     {
658         return response(
659             queue: queue,
660             responseSerializer: DataRequest.propertyListResponseSerializer(options: options),
661             completionHandler: completionHandler
662         )
663     }
664 }
665
666 extension DownloadRequest {
667     /// Creates a response serializer that returns an object constructed from the response data using
668     /// `PropertyListSerialization` with the specified reading options.
669     ///
670     /// - parameter options: The property list reading options. Defaults to `[]`.
671     ///
672     /// - returns: A property list object response serializer.
673     public static func propertyListResponseSerializer(
674         options: PropertyListSerialization.ReadOptions = [])
675         -> DownloadResponseSerializer<Any>
676     {
677         return DownloadResponseSerializer { _, response, fileURL, error in
678             guard error == nil else { return .failure(error!) }
679
680             guard let fileURL = fileURL else {
681                 return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
682             }
683
684             do {
685                 let data = try Data(contentsOf: fileURL)
686                 return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error)
687             } catch {
688                 return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
689             }
690         }
691     }
692
693     /// Adds a handler to be called once the request has finished.
694     ///
695     /// - parameter options:           The property list reading options. Defaults to `[]`.
696     /// - parameter completionHandler: A closure to be executed once the request has finished.
697     ///
698     /// - returns: The request.
699     @discardableResult
700     public func responsePropertyList(
701         queue: DispatchQueue? = nil,
702         options: PropertyListSerialization.ReadOptions = [],
703         completionHandler: @escaping (DownloadResponse<Any>) -> Void)
704         -> Self
705     {
706         return response(
707             queue: queue,
708             responseSerializer: DownloadRequest.propertyListResponseSerializer(options: options),
709             completionHandler: completionHandler
710         )
711     }
712 }
713
714 /// A set of HTTP response status code that do not contain response data.
715 private let emptyDataStatusCodes: Set<Int> = [204, 205]