Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  ResponseSerialization.swift
3
//
4
//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
5
//
6
//  Permission is hereby granted, free of charge, to any person obtaining a copy
7
//  of this software and associated documentation files (the "Software"), to deal
8
//  in the Software without restriction, including without limitation the rights
9
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
//  copies of the Software, and to permit persons to whom the Software is
11
//  furnished to do so, subject to the following conditions:
12
//
13
//  The above copyright notice and this permission notice shall be included in
14
//  all copies or substantial portions of the Software.
15
//
16
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
//  THE SOFTWARE.
23
//
24
 
25
import Foundation
26
 
27
// MARK: Protocols
28
 
29
/// The type to which all data response serializers must conform in order to serialize a response.
30
public protocol DataResponseSerializerProtocol {
31
    /// The type of serialized object to be created.
32
    associatedtype SerializedObject
33
 
34
    /// Serialize the response `Data` into the provided type..
35
    ///
36
    /// - Parameters:
37
    ///   - request:  `URLRequest` which was used to perform the request, if any.
38
    ///   - response: `HTTPURLResponse` received from the server, if any.
39
    ///   - data:     `Data` returned from the server, if any.
40
    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
41
    ///
42
    /// - Returns:    The `SerializedObject`.
43
    /// - Throws:     Any `Error` produced during serialization.
44
    func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> SerializedObject
45
}
46
 
47
/// The type to which all download response serializers must conform in order to serialize a response.
48
public protocol DownloadResponseSerializerProtocol {
49
    /// The type of serialized object to be created.
50
    associatedtype SerializedObject
51
 
52
    /// Serialize the downloaded response `Data` from disk into the provided type..
53
    ///
54
    /// - Parameters:
55
    ///   - request:  `URLRequest` which was used to perform the request, if any.
56
    ///   - response: `HTTPURLResponse` received from the server, if any.
57
    ///   - fileURL:  File `URL` to which the response data was downloaded.
58
    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
59
    ///
60
    /// - Returns:    The `SerializedObject`.
61
    /// - Throws:     Any `Error` produced during serialization.
62
    func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> SerializedObject
63
}
64
 
65
/// A serializer that can handle both data and download responses.
66
public protocol ResponseSerializer: DataResponseSerializerProtocol & DownloadResponseSerializerProtocol {
67
    /// `DataPreprocessor` used to prepare incoming `Data` for serialization.
68
    var dataPreprocessor: DataPreprocessor { get }
69
    /// `HTTPMethod`s for which empty response bodies are considered appropriate.
70
    var emptyRequestMethods: Set<HTTPMethod> { get }
71
    /// HTTP response codes for which empty response bodies are considered appropriate.
72
    var emptyResponseCodes: Set<Int> { get }
73
}
74
 
75
/// Type used to preprocess `Data` before it handled by a serializer.
76
public protocol DataPreprocessor {
77
    /// Process           `Data` before it's handled by a serializer.
78
    /// - Parameter data: The raw `Data` to process.
79
    func preprocess(_ data: Data) throws -> Data
80
}
81
 
82
/// `DataPreprocessor` that returns passed `Data` without any transform.
83
public struct PassthroughPreprocessor: DataPreprocessor {
84
    public init() {}
85
 
86
    public func preprocess(_ data: Data) throws -> Data { data }
87
}
88
 
89
/// `DataPreprocessor` that trims Google's typical `)]}',\n` XSSI JSON header.
90
public struct GoogleXSSIPreprocessor: DataPreprocessor {
91
    public init() {}
92
 
93
    public func preprocess(_ data: Data) throws -> Data {
94
        (data.prefix(6) == Data(")]}',\n".utf8)) ? data.dropFirst(6) : data
95
    }
96
}
97
 
98
#if swift(>=5.5)
99
extension DataPreprocessor where Self == PassthroughPreprocessor {
100
    /// Provides a `PassthroughPreprocessor` instance.
101
    public static var passthrough: PassthroughPreprocessor { PassthroughPreprocessor() }
102
}
103
 
104
extension DataPreprocessor where Self == GoogleXSSIPreprocessor {
105
    /// Provides a `GoogleXSSIPreprocessor` instance.
106
    public static var googleXSSI: GoogleXSSIPreprocessor { GoogleXSSIPreprocessor() }
107
}
108
#endif
109
 
110
extension ResponseSerializer {
111
    /// Default `DataPreprocessor`. `PassthroughPreprocessor` by default.
112
    public static var defaultDataPreprocessor: DataPreprocessor { PassthroughPreprocessor() }
113
    /// Default `HTTPMethod`s for which empty response bodies are considered appropriate. `[.head]` by default.
114
    public static var defaultEmptyRequestMethods: Set<HTTPMethod> { [.head] }
115
    /// HTTP response codes for which empty response bodies are considered appropriate. `[204, 205]` by default.
116
    public static var defaultEmptyResponseCodes: Set<Int> { [204, 205] }
117
 
118
    public var dataPreprocessor: DataPreprocessor { Self.defaultDataPreprocessor }
119
    public var emptyRequestMethods: Set<HTTPMethod> { Self.defaultEmptyRequestMethods }
120
    public var emptyResponseCodes: Set<Int> { Self.defaultEmptyResponseCodes }
121
 
122
    /// Determines whether the `request` allows empty response bodies, if `request` exists.
123
    ///
124
    /// - Parameter request: `URLRequest` to evaluate.
125
    ///
126
    /// - Returns:           `Bool` representing the outcome of the evaluation, or `nil` if `request` was `nil`.
127
    public func requestAllowsEmptyResponseData(_ request: URLRequest?) -> Bool? {
128
        request.flatMap(\.httpMethod)
129
            .flatMap(HTTPMethod.init)
130
            .map { emptyRequestMethods.contains($0) }
131
    }
132
 
133
    /// Determines whether the `response` allows empty response bodies, if `response` exists`.
134
    ///
135
    /// - Parameter response: `HTTPURLResponse` to evaluate.
136
    ///
137
    /// - Returns:            `Bool` representing the outcome of the evaluation, or `nil` if `response` was `nil`.
138
    public func responseAllowsEmptyResponseData(_ response: HTTPURLResponse?) -> Bool? {
139
        response.map(\.statusCode)
140
            .map { emptyResponseCodes.contains($0) }
141
    }
142
 
143
    /// Determines whether `request` and `response` allow empty response bodies.
144
    ///
145
    /// - Parameters:
146
    ///   - request:  `URLRequest` to evaluate.
147
    ///   - response: `HTTPURLResponse` to evaluate.
148
    ///
149
    /// - Returns:    `true` if `request` or `response` allow empty bodies, `false` otherwise.
150
    public func emptyResponseAllowed(forRequest request: URLRequest?, response: HTTPURLResponse?) -> Bool {
151
        (requestAllowsEmptyResponseData(request) == true) || (responseAllowsEmptyResponseData(response) == true)
152
    }
153
}
154
 
155
/// By default, any serializer declared to conform to both types will get file serialization for free, as it just feeds
156
/// the data read from disk into the data response serializer.
157
extension DownloadResponseSerializerProtocol where Self: DataResponseSerializerProtocol {
158
    public func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> Self.SerializedObject {
159
        guard error == nil else { throw error! }
160
 
161
        guard let fileURL = fileURL else {
162
            throw AFError.responseSerializationFailed(reason: .inputFileNil)
163
        }
164
 
165
        let data: Data
166
        do {
167
            data = try Data(contentsOf: fileURL)
168
        } catch {
169
            throw AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))
170
        }
171
 
172
        do {
173
            return try serialize(request: request, response: response, data: data, error: error)
174
        } catch {
175
            throw error
176
        }
177
    }
178
}
179
 
180
// MARK: - Default
181
 
182
extension DataRequest {
183
    /// Adds a handler to be called once the request has finished.
184
    ///
185
    /// - Parameters:
186
    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
187
    ///   - completionHandler: The code to be executed once the request has finished.
188
    ///
189
    /// - Returns:             The request.
190
    @discardableResult
191
    public func response(queue: DispatchQueue = .main, completionHandler: @escaping (AFDataResponse<Data?>) -> Void) -> Self {
192
        appendResponseSerializer {
193
            // Start work that should be on the serialization queue.
194
            let result = AFResult<Data?>(value: self.data, error: self.error)
195
            // End work that should be on the serialization queue.
196
 
197
            self.underlyingQueue.async {
198
                let response = DataResponse(request: self.request,
199
                                            response: self.response,
200
                                            data: self.data,
201
                                            metrics: self.metrics,
202
                                            serializationDuration: 0,
203
                                            result: result)
204
 
205
                self.eventMonitor?.request(self, didParseResponse: response)
206
 
207
                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
208
            }
209
        }
210
 
211
        return self
212
    }
213
 
214
    private func _response<Serializer: DataResponseSerializerProtocol>(queue: DispatchQueue = .main,
215
                                                                       responseSerializer: Serializer,
216
                                                                       completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void)
217
        -> Self {
218
        appendResponseSerializer {
219
            // Start work that should be on the serialization queue.
220
            let start = ProcessInfo.processInfo.systemUptime
221
            let result: AFResult<Serializer.SerializedObject> = Result {
222
                try responseSerializer.serialize(request: self.request,
223
                                                 response: self.response,
224
                                                 data: self.data,
225
                                                 error: self.error)
226
            }.mapError { error in
227
                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
228
            }
229
 
230
            let end = ProcessInfo.processInfo.systemUptime
231
            // End work that should be on the serialization queue.
232
 
233
            self.underlyingQueue.async {
234
                let response = DataResponse(request: self.request,
235
                                            response: self.response,
236
                                            data: self.data,
237
                                            metrics: self.metrics,
238
                                            serializationDuration: end - start,
239
                                            result: result)
240
 
241
                self.eventMonitor?.request(self, didParseResponse: response)
242
 
243
                guard let serializerError = result.failure, let delegate = self.delegate else {
244
                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
245
                    return
246
                }
247
 
248
                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
249
                    var didComplete: (() -> Void)?
250
 
251
                    defer {
252
                        if let didComplete = didComplete {
253
                            self.responseSerializerDidComplete { queue.async { didComplete() } }
254
                        }
255
                    }
256
 
257
                    switch retryResult {
258
                    case .doNotRetry:
259
                        didComplete = { completionHandler(response) }
260
 
261
                    case let .doNotRetryWithError(retryError):
262
                        let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
263
 
264
                        let response = DataResponse(request: self.request,
265
                                                    response: self.response,
266
                                                    data: self.data,
267
                                                    metrics: self.metrics,
268
                                                    serializationDuration: end - start,
269
                                                    result: result)
270
 
271
                        didComplete = { completionHandler(response) }
272
 
273
                    case .retry, .retryWithDelay:
274
                        delegate.retryRequest(self, withDelay: retryResult.delay)
275
                    }
276
                }
277
            }
278
        }
279
 
280
        return self
281
    }
282
 
283
    /// Adds a handler to be called once the request has finished.
284
    ///
285
    /// - Parameters:
286
    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default
287
    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data.
288
    ///   - completionHandler:  The code to be executed once the request has finished.
289
    ///
290
    /// - Returns:              The request.
291
    @discardableResult
292
    public func response<Serializer: DataResponseSerializerProtocol>(queue: DispatchQueue = .main,
293
                                                                     responseSerializer: Serializer,
294
                                                                     completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void)
295
        -> Self {
296
        _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
297
    }
298
 
299
    /// Adds a handler to be called once the request has finished.
300
    ///
301
    /// - Parameters:
302
    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default
303
    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data.
304
    ///   - completionHandler:  The code to be executed once the request has finished.
305
    ///
306
    /// - Returns:              The request.
307
    @discardableResult
308
    public func response<Serializer: ResponseSerializer>(queue: DispatchQueue = .main,
309
                                                         responseSerializer: Serializer,
310
                                                         completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void)
311
        -> Self {
312
        _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
313
    }
314
}
315
 
316
extension DownloadRequest {
317
    /// Adds a handler to be called once the request has finished.
318
    ///
319
    /// - Parameters:
320
    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
321
    ///   - completionHandler: The code to be executed once the request has finished.
322
    ///
323
    /// - Returns:             The request.
324
    @discardableResult
325
    public func response(queue: DispatchQueue = .main,
326
                         completionHandler: @escaping (AFDownloadResponse<URL?>) -> Void)
327
        -> Self {
328
        appendResponseSerializer {
329
            // Start work that should be on the serialization queue.
330
            let result = AFResult<URL?>(value: self.fileURL, error: self.error)
331
            // End work that should be on the serialization queue.
332
 
333
            self.underlyingQueue.async {
334
                let response = DownloadResponse(request: self.request,
335
                                                response: self.response,
336
                                                fileURL: self.fileURL,
337
                                                resumeData: self.resumeData,
338
                                                metrics: self.metrics,
339
                                                serializationDuration: 0,
340
                                                result: result)
341
 
342
                self.eventMonitor?.request(self, didParseResponse: response)
343
 
344
                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
345
            }
346
        }
347
 
348
        return self
349
    }
350
 
351
    private func _response<Serializer: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
352
                                                                           responseSerializer: Serializer,
353
                                                                           completionHandler: @escaping (AFDownloadResponse<Serializer.SerializedObject>) -> Void)
354
        -> Self {
355
        appendResponseSerializer {
356
            // Start work that should be on the serialization queue.
357
            let start = ProcessInfo.processInfo.systemUptime
358
            let result: AFResult<Serializer.SerializedObject> = Result {
359
                try responseSerializer.serializeDownload(request: self.request,
360
                                                         response: self.response,
361
                                                         fileURL: self.fileURL,
362
                                                         error: self.error)
363
            }.mapError { error in
364
                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
365
            }
366
            let end = ProcessInfo.processInfo.systemUptime
367
            // End work that should be on the serialization queue.
368
 
369
            self.underlyingQueue.async {
370
                let response = DownloadResponse(request: self.request,
371
                                                response: self.response,
372
                                                fileURL: self.fileURL,
373
                                                resumeData: self.resumeData,
374
                                                metrics: self.metrics,
375
                                                serializationDuration: end - start,
376
                                                result: result)
377
 
378
                self.eventMonitor?.request(self, didParseResponse: response)
379
 
380
                guard let serializerError = result.failure, let delegate = self.delegate else {
381
                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
382
                    return
383
                }
384
 
385
                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
386
                    var didComplete: (() -> Void)?
387
 
388
                    defer {
389
                        if let didComplete = didComplete {
390
                            self.responseSerializerDidComplete { queue.async { didComplete() } }
391
                        }
392
                    }
393
 
394
                    switch retryResult {
395
                    case .doNotRetry:
396
                        didComplete = { completionHandler(response) }
397
 
398
                    case let .doNotRetryWithError(retryError):
399
                        let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
400
 
401
                        let response = DownloadResponse(request: self.request,
402
                                                        response: self.response,
403
                                                        fileURL: self.fileURL,
404
                                                        resumeData: self.resumeData,
405
                                                        metrics: self.metrics,
406
                                                        serializationDuration: end - start,
407
                                                        result: result)
408
 
409
                        didComplete = { completionHandler(response) }
410
 
411
                    case .retry, .retryWithDelay:
412
                        delegate.retryRequest(self, withDelay: retryResult.delay)
413
                    }
414
                }
415
            }
416
        }
417
 
418
        return self
419
    }
420
 
421
    /// Adds a handler to be called once the request has finished.
422
    ///
423
    /// - Parameters:
424
    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default.
425
    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data
426
    ///                         contained in the destination `URL`.
427
    ///   - completionHandler:  The code to be executed once the request has finished.
428
    ///
429
    /// - Returns:              The request.
430
    @discardableResult
431
    public func response<Serializer: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
432
                                                                         responseSerializer: Serializer,
433
                                                                         completionHandler: @escaping (AFDownloadResponse<Serializer.SerializedObject>) -> Void)
434
        -> Self {
435
        _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
436
    }
437
 
438
    /// Adds a handler to be called once the request has finished.
439
    ///
440
    /// - Parameters:
441
    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default.
442
    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data
443
    ///                         contained in the destination `URL`.
444
    ///   - completionHandler:  The code to be executed once the request has finished.
445
    ///
446
    /// - Returns:              The request.
447
    @discardableResult
448
    public func response<Serializer: ResponseSerializer>(queue: DispatchQueue = .main,
449
                                                         responseSerializer: Serializer,
450
                                                         completionHandler: @escaping (AFDownloadResponse<Serializer.SerializedObject>) -> Void)
451
        -> Self {
452
        _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
453
    }
454
}
455
 
456
// MARK: - URL
457
 
458
/// A `DownloadResponseSerializerProtocol` that performs only `Error` checking and ensures that a downloaded `fileURL`
459
/// is present.
460
public struct URLResponseSerializer: DownloadResponseSerializerProtocol {
461
    /// Creates an instance.
462
    public init() {}
463
 
464
    public func serializeDownload(request: URLRequest?,
465
                                  response: HTTPURLResponse?,
466
                                  fileURL: URL?,
467
                                  error: Error?) throws -> URL {
468
        guard error == nil else { throw error! }
469
 
470
        guard let url = fileURL else {
471
            throw AFError.responseSerializationFailed(reason: .inputFileNil)
472
        }
473
 
474
        return url
475
    }
476
}
477
 
478
#if swift(>=5.5)
479
extension DownloadResponseSerializerProtocol where Self == URLResponseSerializer {
480
    /// Provides a `URLResponseSerializer` instance.
481
    public static var url: URLResponseSerializer { URLResponseSerializer() }
482
}
483
#endif
484
 
485
extension DownloadRequest {
486
    /// Adds a handler using a `URLResponseSerializer` to be called once the request is finished.
487
    ///
488
    /// - Parameters:
489
    ///   - queue:             The queue on which the completion handler is called. `.main` by default.
490
    ///   - completionHandler: A closure to be executed once the request has finished.
491
    ///
492
    /// - Returns:             The request.
493
    @discardableResult
494
    public func responseURL(queue: DispatchQueue = .main,
495
                            completionHandler: @escaping (AFDownloadResponse<URL>) -> Void) -> Self {
496
        response(queue: queue, responseSerializer: URLResponseSerializer(), completionHandler: completionHandler)
497
    }
498
}
499
 
500
// MARK: - Data
501
 
502
/// A `ResponseSerializer` that performs minimal response checking and returns any response `Data` as-is. By default, a
503
/// request returning `nil` or no data is considered an error. However, if the request has an `HTTPMethod` or the
504
/// response has an  HTTP status code valid for empty responses, then an empty `Data` value is returned.
505
public final class DataResponseSerializer: ResponseSerializer {
506
    public let dataPreprocessor: DataPreprocessor
507
    public let emptyResponseCodes: Set<Int>
508
    public let emptyRequestMethods: Set<HTTPMethod>
509
 
510
    /// Creates a `DataResponseSerializer` using the provided parameters.
511
    ///
512
    /// - Parameters:
513
    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
514
    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
515
    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
516
    public init(dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
517
                emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
518
                emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) {
519
        self.dataPreprocessor = dataPreprocessor
520
        self.emptyResponseCodes = emptyResponseCodes
521
        self.emptyRequestMethods = emptyRequestMethods
522
    }
523
 
524
    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Data {
525
        guard error == nil else { throw error! }
526
 
527
        guard var data = data, !data.isEmpty else {
528
            guard emptyResponseAllowed(forRequest: request, response: response) else {
529
                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
530
            }
531
 
532
            return Data()
533
        }
534
 
535
        data = try dataPreprocessor.preprocess(data)
536
 
537
        return data
538
    }
539
}
540
 
541
#if swift(>=5.5)
542
extension ResponseSerializer where Self == DataResponseSerializer {
543
    /// Provides a default `DataResponseSerializer` instance.
544
    public static var data: DataResponseSerializer { DataResponseSerializer() }
545
 
546
    /// Creates a `DataResponseSerializer` using the provided parameters.
547
    ///
548
    /// - Parameters:
549
    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
550
    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
551
    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
552
    ///
553
    /// - Returns:               The `DataResponseSerializer`.
554
    public static func data(dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
555
                            emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
556
                            emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DataResponseSerializer {
557
        DataResponseSerializer(dataPreprocessor: dataPreprocessor,
558
                               emptyResponseCodes: emptyResponseCodes,
559
                               emptyRequestMethods: emptyRequestMethods)
560
    }
561
}
562
#endif
563
 
564
extension DataRequest {
565
    /// Adds a handler using a `DataResponseSerializer` to be called once the request has finished.
566
    ///
567
    /// - Parameters:
568
    ///   - queue:               The queue on which the completion handler is called. `.main` by default.
569
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
570
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
571
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
572
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
573
    ///   - completionHandler:   A closure to be executed once the request has finished.
574
    ///
575
    /// - Returns:               The request.
576
    @discardableResult
577
    public func responseData(queue: DispatchQueue = .main,
578
                             dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
579
                             emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
580
                             emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods,
581
                             completionHandler: @escaping (AFDataResponse<Data>) -> Void) -> Self {
582
        response(queue: queue,
583
                 responseSerializer: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
584
                                                            emptyResponseCodes: emptyResponseCodes,
585
                                                            emptyRequestMethods: emptyRequestMethods),
586
                 completionHandler: completionHandler)
587
    }
588
}
589
 
590
extension DownloadRequest {
591
    /// Adds a handler using a `DataResponseSerializer` to be called once the request has finished.
592
    ///
593
    /// - Parameters:
594
    ///   - queue:               The queue on which the completion handler is called. `.main` by default.
595
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
596
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
597
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
598
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
599
    ///   - completionHandler:   A closure to be executed once the request has finished.
600
    ///
601
    /// - Returns:               The request.
602
    @discardableResult
603
    public func responseData(queue: DispatchQueue = .main,
604
                             dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
605
                             emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
606
                             emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods,
607
                             completionHandler: @escaping (AFDownloadResponse<Data>) -> Void) -> Self {
608
        response(queue: queue,
609
                 responseSerializer: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
610
                                                            emptyResponseCodes: emptyResponseCodes,
611
                                                            emptyRequestMethods: emptyRequestMethods),
612
                 completionHandler: completionHandler)
613
    }
614
}
615
 
616
// MARK: - String
617
 
618
/// A `ResponseSerializer` that decodes the response data as a `String`. By default, a request returning `nil` or no
619
/// data is considered an error. However, if the request has an `HTTPMethod` or the response has an  HTTP status code
620
/// valid for empty responses, then an empty `String` is returned.
621
public final class StringResponseSerializer: ResponseSerializer {
622
    public let dataPreprocessor: DataPreprocessor
623
    /// Optional string encoding used to validate the response.
624
    public let encoding: String.Encoding?
625
    public let emptyResponseCodes: Set<Int>
626
    public let emptyRequestMethods: Set<HTTPMethod>
627
 
628
    /// Creates an instance with the provided values.
629
    ///
630
    /// - Parameters:
631
    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
632
    ///   - encoding:            A string encoding. Defaults to `nil`, in which case the encoding will be determined
633
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
634
    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
635
    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
636
    public init(dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
637
                encoding: String.Encoding? = nil,
638
                emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
639
                emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) {
640
        self.dataPreprocessor = dataPreprocessor
641
        self.encoding = encoding
642
        self.emptyResponseCodes = emptyResponseCodes
643
        self.emptyRequestMethods = emptyRequestMethods
644
    }
645
 
646
    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> String {
647
        guard error == nil else { throw error! }
648
 
649
        guard var data = data, !data.isEmpty else {
650
            guard emptyResponseAllowed(forRequest: request, response: response) else {
651
                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
652
            }
653
 
654
            return ""
655
        }
656
 
657
        data = try dataPreprocessor.preprocess(data)
658
 
659
        var convertedEncoding = encoding
660
 
661
        if let encodingName = response?.textEncodingName, convertedEncoding == nil {
662
            convertedEncoding = String.Encoding(ianaCharsetName: encodingName)
663
        }
664
 
665
        let actualEncoding = convertedEncoding ?? .isoLatin1
666
 
667
        guard let string = String(data: data, encoding: actualEncoding) else {
668
            throw AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding))
669
        }
670
 
671
        return string
672
    }
673
}
674
 
675
#if swift(>=5.5)
676
extension ResponseSerializer where Self == StringResponseSerializer {
677
    /// Provides a default `StringResponseSerializer` instance.
678
    public static var string: StringResponseSerializer { StringResponseSerializer() }
679
 
680
    /// Creates a `StringResponseSerializer` with the provided values.
681
    ///
682
    /// - Parameters:
683
    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
684
    ///   - encoding:            A string encoding. Defaults to `nil`, in which case the encoding will be determined
685
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
686
    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
687
    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
688
    ///
689
    /// - Returns:               The `StringResponseSerializer`.
690
    public static func string(dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
691
                              encoding: String.Encoding? = nil,
692
                              emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
693
                              emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) -> StringResponseSerializer {
694
        StringResponseSerializer(dataPreprocessor: dataPreprocessor,
695
                                 encoding: encoding,
696
                                 emptyResponseCodes: emptyResponseCodes,
697
                                 emptyRequestMethods: emptyRequestMethods)
698
    }
699
}
700
#endif
701
 
702
extension DataRequest {
703
    /// Adds a handler using a `StringResponseSerializer` to be called once the request has finished.
704
    ///
705
    /// - Parameters:
706
    ///   - queue:               The queue on which the completion handler is dispatched. `.main` by default.
707
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
708
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
709
    ///   - encoding:            The string encoding. Defaults to `nil`, in which case the encoding will be determined
710
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
711
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
712
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
713
    ///   - completionHandler:   A closure to be executed once the request has finished.
714
    ///
715
    /// - Returns:               The request.
716
    @discardableResult
717
    public func responseString(queue: DispatchQueue = .main,
718
                               dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
719
                               encoding: String.Encoding? = nil,
720
                               emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
721
                               emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods,
722
                               completionHandler: @escaping (AFDataResponse<String>) -> Void) -> Self {
723
        response(queue: queue,
724
                 responseSerializer: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
725
                                                              encoding: encoding,
726
                                                              emptyResponseCodes: emptyResponseCodes,
727
                                                              emptyRequestMethods: emptyRequestMethods),
728
                 completionHandler: completionHandler)
729
    }
730
}
731
 
732
extension DownloadRequest {
733
    /// Adds a handler using a `StringResponseSerializer` to be called once the request has finished.
734
    ///
735
    /// - Parameters:
736
    ///   - queue:               The queue on which the completion handler is dispatched. `.main` by default.
737
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
738
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
739
    ///   - encoding:            The string encoding. Defaults to `nil`, in which case the encoding will be determined
740
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
741
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
742
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
743
    ///   - completionHandler:   A closure to be executed once the request has finished.
744
    ///
745
    /// - Returns:               The request.
746
    @discardableResult
747
    public func responseString(queue: DispatchQueue = .main,
748
                               dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
749
                               encoding: String.Encoding? = nil,
750
                               emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
751
                               emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods,
752
                               completionHandler: @escaping (AFDownloadResponse<String>) -> Void) -> Self {
753
        response(queue: queue,
754
                 responseSerializer: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
755
                                                              encoding: encoding,
756
                                                              emptyResponseCodes: emptyResponseCodes,
757
                                                              emptyRequestMethods: emptyRequestMethods),
758
                 completionHandler: completionHandler)
759
    }
760
}
761
 
762
// MARK: - JSON
763
 
764
/// A `ResponseSerializer` that decodes the response data using `JSONSerialization`. By default, a request returning
765
/// `nil` or no data is considered an error. However, if the request has an `HTTPMethod` or the response has an
766
/// HTTP status code valid for empty responses, then an `NSNull` value is returned.
767
@available(*, deprecated, message: "JSONResponseSerializer deprecated and will be removed in Alamofire 6. Use DecodableResponseSerializer instead.")
768
public final class JSONResponseSerializer: ResponseSerializer {
769
    public let dataPreprocessor: DataPreprocessor
770
    public let emptyResponseCodes: Set<Int>
771
    public let emptyRequestMethods: Set<HTTPMethod>
772
    /// `JSONSerialization.ReadingOptions` used when serializing a response.
773
    public let options: JSONSerialization.ReadingOptions
774
 
775
    /// Creates an instance with the provided values.
776
    ///
777
    /// - Parameters:
778
    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
779
    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
780
    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
781
    ///   - options:             The options to use. `.allowFragments` by default.
782
    public init(dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
783
                emptyResponseCodes: Set<Int> = JSONResponseSerializer.defaultEmptyResponseCodes,
784
                emptyRequestMethods: Set<HTTPMethod> = JSONResponseSerializer.defaultEmptyRequestMethods,
785
                options: JSONSerialization.ReadingOptions = .allowFragments) {
786
        self.dataPreprocessor = dataPreprocessor
787
        self.emptyResponseCodes = emptyResponseCodes
788
        self.emptyRequestMethods = emptyRequestMethods
789
        self.options = options
790
    }
791
 
792
    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Any {
793
        guard error == nil else { throw error! }
794
 
795
        guard var data = data, !data.isEmpty else {
796
            guard emptyResponseAllowed(forRequest: request, response: response) else {
797
                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
798
            }
799
 
800
            return NSNull()
801
        }
802
 
803
        data = try dataPreprocessor.preprocess(data)
804
 
805
        do {
806
            return try JSONSerialization.jsonObject(with: data, options: options)
807
        } catch {
808
            throw AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error))
809
        }
810
    }
811
}
812
 
813
extension DataRequest {
814
    /// Adds a handler using a `JSONResponseSerializer` to be called once the request has finished.
815
    ///
816
    /// - Parameters:
817
    ///   - queue:               The queue on which the completion handler is dispatched. `.main` by default.
818
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
819
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
820
    ///   - encoding:            The string encoding. Defaults to `nil`, in which case the encoding will be determined
821
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
822
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
823
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
824
    ///   - options:             `JSONSerialization.ReadingOptions` used when parsing the response. `.allowFragments`
825
    ///                          by default.
826
    ///   - completionHandler:   A closure to be executed once the request has finished.
827
    ///
828
    /// - Returns:               The request.
829
    @available(*, deprecated, message: "responseJSON deprecated and will be removed in Alamofire 6. Use responseDecodable instead.")
830
    @discardableResult
831
    public func responseJSON(queue: DispatchQueue = .main,
832
                             dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
833
                             emptyResponseCodes: Set<Int> = JSONResponseSerializer.defaultEmptyResponseCodes,
834
                             emptyRequestMethods: Set<HTTPMethod> = JSONResponseSerializer.defaultEmptyRequestMethods,
835
                             options: JSONSerialization.ReadingOptions = .allowFragments,
836
                             completionHandler: @escaping (AFDataResponse<Any>) -> Void) -> Self {
837
        response(queue: queue,
838
                 responseSerializer: JSONResponseSerializer(dataPreprocessor: dataPreprocessor,
839
                                                            emptyResponseCodes: emptyResponseCodes,
840
                                                            emptyRequestMethods: emptyRequestMethods,
841
                                                            options: options),
842
                 completionHandler: completionHandler)
843
    }
844
}
845
 
846
extension DownloadRequest {
847
    /// Adds a handler using a `JSONResponseSerializer` to be called once the request has finished.
848
    ///
849
    /// - Parameters:
850
    ///   - queue:               The queue on which the completion handler is dispatched. `.main` by default.
851
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
852
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
853
    ///   - encoding:            The string encoding. Defaults to `nil`, in which case the encoding will be determined
854
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
855
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
856
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
857
    ///   - options:             `JSONSerialization.ReadingOptions` used when parsing the response. `.allowFragments`
858
    ///                          by default.
859
    ///   - completionHandler:   A closure to be executed once the request has finished.
860
    ///
861
    /// - Returns:               The request.
862
    @available(*, deprecated, message: "responseJSON deprecated and will be removed in Alamofire 6. Use responseDecodable instead.")
863
    @discardableResult
864
    public func responseJSON(queue: DispatchQueue = .main,
865
                             dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
866
                             emptyResponseCodes: Set<Int> = JSONResponseSerializer.defaultEmptyResponseCodes,
867
                             emptyRequestMethods: Set<HTTPMethod> = JSONResponseSerializer.defaultEmptyRequestMethods,
868
                             options: JSONSerialization.ReadingOptions = .allowFragments,
869
                             completionHandler: @escaping (AFDownloadResponse<Any>) -> Void) -> Self {
870
        response(queue: queue,
871
                 responseSerializer: JSONResponseSerializer(dataPreprocessor: dataPreprocessor,
872
                                                            emptyResponseCodes: emptyResponseCodes,
873
                                                            emptyRequestMethods: emptyRequestMethods,
874
                                                            options: options),
875
                 completionHandler: completionHandler)
876
    }
877
}
878
 
879
// MARK: - Empty
880
 
881
/// Protocol representing an empty response. Use `T.emptyValue()` to get an instance.
882
public protocol EmptyResponse {
883
    /// Empty value for the conforming type.
884
    ///
885
    /// - Returns: Value of `Self` to use for empty values.
886
    static func emptyValue() -> Self
887
}
888
 
889
/// Type representing an empty value. Use `Empty.value` to get the static instance.
890
public struct Empty: Codable {
891
    /// Static `Empty` instance used for all `Empty` responses.
892
    public static let value = Empty()
893
}
894
 
895
extension Empty: EmptyResponse {
896
    public static func emptyValue() -> Empty {
897
        value
898
    }
899
}
900
 
901
// MARK: - DataDecoder Protocol
902
 
903
/// Any type which can decode `Data` into a `Decodable` type.
904
public protocol DataDecoder {
905
    /// Decode `Data` into the provided type.
906
    ///
907
    /// - Parameters:
908
    ///   - type:  The `Type` to be decoded.
909
    ///   - data:  The `Data` to be decoded.
910
    ///
911
    /// - Returns: The decoded value of type `D`.
912
    /// - Throws:  Any error that occurs during decode.
913
    func decode<D: Decodable>(_ type: D.Type, from data: Data) throws -> D
914
}
915
 
916
/// `JSONDecoder` automatically conforms to `DataDecoder`.
917
extension JSONDecoder: DataDecoder {}
918
/// `PropertyListDecoder` automatically conforms to `DataDecoder`.
919
extension PropertyListDecoder: DataDecoder {}
920
 
921
// MARK: - Decodable
922
 
923
/// A `ResponseSerializer` that decodes the response data as a generic value using any type that conforms to
924
/// `DataDecoder`. By default, this is an instance of `JSONDecoder`. Additionally, a request returning `nil` or no data
925
/// is considered an error. However, if the request has an `HTTPMethod` or the response has an HTTP status code valid
926
/// for empty responses then an empty value will be returned. If the decoded type conforms to `EmptyResponse`, the
927
/// type's `emptyValue()` will be returned. If the decoded type is `Empty`, the `.value` instance is returned. If the
928
/// decoded type *does not* conform to `EmptyResponse` and isn't `Empty`, an error will be produced.
929
public final class DecodableResponseSerializer<T: Decodable>: ResponseSerializer {
930
    public let dataPreprocessor: DataPreprocessor
931
    /// The `DataDecoder` instance used to decode responses.
932
    public let decoder: DataDecoder
933
    public let emptyResponseCodes: Set<Int>
934
    public let emptyRequestMethods: Set<HTTPMethod>
935
 
936
    /// Creates an instance using the values provided.
937
    ///
938
    /// - Parameters:
939
    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
940
    ///   - decoder:             The `DataDecoder`. `JSONDecoder()` by default.
941
    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
942
    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
943
    public init(dataPreprocessor: DataPreprocessor = DecodableResponseSerializer.defaultDataPreprocessor,
944
                decoder: DataDecoder = JSONDecoder(),
945
                emptyResponseCodes: Set<Int> = DecodableResponseSerializer.defaultEmptyResponseCodes,
946
                emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer.defaultEmptyRequestMethods) {
947
        self.dataPreprocessor = dataPreprocessor
948
        self.decoder = decoder
949
        self.emptyResponseCodes = emptyResponseCodes
950
        self.emptyRequestMethods = emptyRequestMethods
951
    }
952
 
953
    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> T {
954
        guard error == nil else { throw error! }
955
 
956
        guard var data = data, !data.isEmpty else {
957
            guard emptyResponseAllowed(forRequest: request, response: response) else {
958
                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
959
            }
960
 
961
            guard let emptyResponseType = T.self as? EmptyResponse.Type, let emptyValue = emptyResponseType.emptyValue() as? T else {
962
                throw AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "\(T.self)"))
963
            }
964
 
965
            return emptyValue
966
        }
967
 
968
        data = try dataPreprocessor.preprocess(data)
969
 
970
        do {
971
            return try decoder.decode(T.self, from: data)
972
        } catch {
973
            throw AFError.responseSerializationFailed(reason: .decodingFailed(error: error))
974
        }
975
    }
976
}
977
 
978
#if swift(>=5.5)
979
extension ResponseSerializer {
980
    /// Creates a `DecodableResponseSerializer` using the values provided.
981
    ///
982
    /// - Parameters:
983
    ///   - type:                `Decodable` type to decode from response data.
984
    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
985
    ///   - decoder:             The `DataDecoder`. `JSONDecoder()` by default.
986
    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
987
    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
988
    ///
989
    /// - Returns:               The `DecodableResponseSerializer`.
990
    public static func decodable<T: Decodable>(of type: T.Type,
991
                                               dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
992
                                               decoder: DataDecoder = JSONDecoder(),
993
                                               emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
994
                                               emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods) -> DecodableResponseSerializer<T> where Self == DecodableResponseSerializer<T> {
995
        DecodableResponseSerializer<T>(dataPreprocessor: dataPreprocessor,
996
                                       decoder: decoder,
997
                                       emptyResponseCodes: emptyResponseCodes,
998
                                       emptyRequestMethods: emptyRequestMethods)
999
    }
1000
}
1001
#endif
1002
 
1003
extension DataRequest {
1004
    /// Adds a handler using a `DecodableResponseSerializer` to be called once the request has finished.
1005
    ///
1006
    /// - Parameters:
1007
    ///   - type:                `Decodable` type to decode from response data.
1008
    ///   - queue:               The queue on which the completion handler is dispatched. `.main` by default.
1009
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
1010
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
1011
    ///   - decoder:             `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
1012
    ///   - encoding:            The string encoding. Defaults to `nil`, in which case the encoding will be determined
1013
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
1014
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
1015
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
1016
    ///   - completionHandler:   A closure to be executed once the request has finished.
1017
    ///
1018
    /// - Returns:               The request.
1019
    @discardableResult
1020
    public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
1021
                                                queue: DispatchQueue = .main,
1022
                                                dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
1023
                                                decoder: DataDecoder = JSONDecoder(),
1024
                                                emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
1025
                                                emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods,
1026
                                                completionHandler: @escaping (AFDataResponse<T>) -> Void) -> Self {
1027
        response(queue: queue,
1028
                 responseSerializer: DecodableResponseSerializer(dataPreprocessor: dataPreprocessor,
1029
                                                                 decoder: decoder,
1030
                                                                 emptyResponseCodes: emptyResponseCodes,
1031
                                                                 emptyRequestMethods: emptyRequestMethods),
1032
                 completionHandler: completionHandler)
1033
    }
1034
}
1035
 
1036
extension DownloadRequest {
1037
    /// Adds a handler using a `DecodableResponseSerializer` to be called once the request has finished.
1038
    ///
1039
    /// - Parameters:
1040
    ///   - type:                `Decodable` type to decode from response data.
1041
    ///   - queue:               The queue on which the completion handler is dispatched. `.main` by default.
1042
    ///   - dataPreprocessor:    `DataPreprocessor` which processes the received `Data` before calling the
1043
    ///                          `completionHandler`. `PassthroughPreprocessor()` by default.
1044
    ///   - decoder:             `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
1045
    ///   - encoding:            The string encoding. Defaults to `nil`, in which case the encoding will be determined
1046
    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
1047
    ///   - emptyResponseCodes:  HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
1048
    ///   - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
1049
    ///   - completionHandler:   A closure to be executed once the request has finished.
1050
    ///
1051
    /// - Returns:               The request.
1052
    @discardableResult
1053
    public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
1054
                                                queue: DispatchQueue = .main,
1055
                                                dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
1056
                                                decoder: DataDecoder = JSONDecoder(),
1057
                                                emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
1058
                                                emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods,
1059
                                                completionHandler: @escaping (AFDownloadResponse<T>) -> Void) -> Self {
1060
        response(queue: queue,
1061
                 responseSerializer: DecodableResponseSerializer(dataPreprocessor: dataPreprocessor,
1062
                                                                 decoder: decoder,
1063
                                                                 emptyResponseCodes: emptyResponseCodes,
1064
                                                                 emptyRequestMethods: emptyRequestMethods),
1065
                 completionHandler: completionHandler)
1066
    }
1067
}
1068
 
1069
// MARK: - DataStreamRequest
1070
 
1071
/// A type which can serialize incoming `Data`.
1072
public protocol DataStreamSerializer {
1073
    /// Type produced from the serialized `Data`.
1074
    associatedtype SerializedObject
1075
 
1076
    /// Serializes incoming `Data` into a `SerializedObject` value.
1077
    ///
1078
    /// - Parameter data: `Data` to be serialized.
1079
    ///
1080
    /// - Throws: Any error produced during serialization.
1081
    func serialize(_ data: Data) throws -> SerializedObject
1082
}
1083
 
1084
/// `DataStreamSerializer` which uses the provided `DataPreprocessor` and `DataDecoder` to serialize the incoming `Data`.
1085
public struct DecodableStreamSerializer<T: Decodable>: DataStreamSerializer {
1086
    /// `DataDecoder` used to decode incoming `Data`.
1087
    public let decoder: DataDecoder
1088
    /// `DataPreprocessor` incoming `Data` is passed through before being passed to the `DataDecoder`.
1089
    public let dataPreprocessor: DataPreprocessor
1090
 
1091
    /// Creates an instance with the provided `DataDecoder` and `DataPreprocessor`.
1092
    /// - Parameters:
1093
    ///   - decoder: `        DataDecoder` used to decode incoming `Data`. `JSONDecoder()` by default.
1094
    ///   - dataPreprocessor: `DataPreprocessor` used to process incoming `Data` before it's passed through the
1095
    ///                       `decoder`. `PassthroughPreprocessor()` by default.
1096
    public init(decoder: DataDecoder = JSONDecoder(), dataPreprocessor: DataPreprocessor = PassthroughPreprocessor()) {
1097
        self.decoder = decoder
1098
        self.dataPreprocessor = dataPreprocessor
1099
    }
1100
 
1101
    public func serialize(_ data: Data) throws -> T {
1102
        let processedData = try dataPreprocessor.preprocess(data)
1103
        do {
1104
            return try decoder.decode(T.self, from: processedData)
1105
        } catch {
1106
            throw AFError.responseSerializationFailed(reason: .decodingFailed(error: error))
1107
        }
1108
    }
1109
}
1110
 
1111
/// `DataStreamSerializer` which performs no serialization on incoming `Data`.
1112
public struct PassthroughStreamSerializer: DataStreamSerializer {
1113
    /// Creates an instance.
1114
    public init() {}
1115
 
1116
    public func serialize(_ data: Data) throws -> Data { data }
1117
}
1118
 
1119
/// `DataStreamSerializer` which serializes incoming stream `Data` into `UTF8`-decoded `String` values.
1120
public struct StringStreamSerializer: DataStreamSerializer {
1121
    /// Creates an instance.
1122
    public init() {}
1123
 
1124
    public func serialize(_ data: Data) throws -> String {
1125
        String(decoding: data, as: UTF8.self)
1126
    }
1127
}
1128
 
1129
#if swift(>=5.5)
1130
extension DataStreamSerializer {
1131
    /// Creates a `DecodableStreamSerializer` instance with the provided `DataDecoder` and `DataPreprocessor`.
1132
    ///
1133
    /// - Parameters:
1134
    ///   - type:             `Decodable` type to decode from stream data.
1135
    ///   - decoder: `        DataDecoder` used to decode incoming `Data`. `JSONDecoder()` by default.
1136
    ///   - dataPreprocessor: `DataPreprocessor` used to process incoming `Data` before it's passed through the
1137
    ///                       `decoder`. `PassthroughPreprocessor()` by default.
1138
    public static func decodable<T: Decodable>(of type: T.Type,
1139
                                               decoder: DataDecoder = JSONDecoder(),
1140
                                               dataPreprocessor: DataPreprocessor = PassthroughPreprocessor()) -> Self where Self == DecodableStreamSerializer<T> {
1141
        DecodableStreamSerializer<T>(decoder: decoder, dataPreprocessor: dataPreprocessor)
1142
    }
1143
}
1144
 
1145
extension DataStreamSerializer where Self == PassthroughStreamSerializer {
1146
    /// Provides a `PassthroughStreamSerializer` instance.
1147
    public static var passthrough: PassthroughStreamSerializer { PassthroughStreamSerializer() }
1148
}
1149
 
1150
extension DataStreamSerializer where Self == StringStreamSerializer {
1151
    /// Provides a `StringStreamSerializer` instance.
1152
    public static var string: StringStreamSerializer { StringStreamSerializer() }
1153
}
1154
#endif
1155
 
1156
extension DataStreamRequest {
1157
    /// Adds a `StreamHandler` which performs no parsing on incoming `Data`.
1158
    ///
1159
    /// - Parameters:
1160
    ///   - queue:  `DispatchQueue` on which to perform `StreamHandler` closure.
1161
    ///   - stream: `StreamHandler` closure called as `Data` is received. May be called multiple times.
1162
    ///
1163
    /// - Returns:  The `DataStreamRequest`.
1164
    @discardableResult
1165
    public func responseStream(on queue: DispatchQueue = .main, stream: @escaping Handler<Data, Never>) -> Self {
1166
        let parser = { [unowned self] (data: Data) in
1167
            queue.async {
1168
                self.capturingError {
1169
                    try stream(.init(event: .stream(.success(data)), token: .init(self)))
1170
                }
1171
 
1172
                self.updateAndCompleteIfPossible()
1173
            }
1174
        }
1175
 
1176
        $streamMutableState.write { $0.streams.append(parser) }
1177
        appendStreamCompletion(on: queue, stream: stream)
1178
 
1179
        return self
1180
    }
1181
 
1182
    /// Adds a `StreamHandler` which uses the provided `DataStreamSerializer` to process incoming `Data`.
1183
    ///
1184
    /// - Parameters:
1185
    ///   - serializer: `DataStreamSerializer` used to process incoming `Data`. Its work is done on the `serializationQueue`.
1186
    ///   - queue:      `DispatchQueue` on which to perform `StreamHandler` closure.
1187
    ///   - stream:     `StreamHandler` closure called as `Data` is received. May be called multiple times.
1188
    ///
1189
    /// - Returns:      The `DataStreamRequest`.
1190
    @discardableResult
1191
    public func responseStream<Serializer: DataStreamSerializer>(using serializer: Serializer,
1192
                                                                 on queue: DispatchQueue = .main,
1193
                                                                 stream: @escaping Handler<Serializer.SerializedObject, AFError>) -> Self {
1194
        let parser = { [unowned self] (data: Data) in
1195
            self.serializationQueue.async {
1196
                // Start work on serialization queue.
1197
                let result = Result { try serializer.serialize(data) }
1198
                    .mapError { $0.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: $0))) }
1199
                // End work on serialization queue.
1200
                self.underlyingQueue.async {
1201
                    self.eventMonitor?.request(self, didParseStream: result)
1202
 
1203
                    if result.isFailure, self.automaticallyCancelOnStreamError {
1204
                        self.cancel()
1205
                    }
1206
 
1207
                    queue.async {
1208
                        self.capturingError {
1209
                            try stream(.init(event: .stream(result), token: .init(self)))
1210
                        }
1211
 
1212
                        self.updateAndCompleteIfPossible()
1213
                    }
1214
                }
1215
            }
1216
        }
1217
 
1218
        $streamMutableState.write { $0.streams.append(parser) }
1219
        appendStreamCompletion(on: queue, stream: stream)
1220
 
1221
        return self
1222
    }
1223
 
1224
    /// Adds a `StreamHandler` which parses incoming `Data` as a UTF8 `String`.
1225
    ///
1226
    /// - Parameters:
1227
    ///   - queue:      `DispatchQueue` on which to perform `StreamHandler` closure.
1228
    ///   - stream:     `StreamHandler` closure called as `Data` is received. May be called multiple times.
1229
    ///
1230
    /// - Returns:  The `DataStreamRequest`.
1231
    @discardableResult
1232
    public func responseStreamString(on queue: DispatchQueue = .main,
1233
                                     stream: @escaping Handler<String, Never>) -> Self {
1234
        let parser = { [unowned self] (data: Data) in
1235
            self.serializationQueue.async {
1236
                // Start work on serialization queue.
1237
                let string = String(decoding: data, as: UTF8.self)
1238
                // End work on serialization queue.
1239
                self.underlyingQueue.async {
1240
                    self.eventMonitor?.request(self, didParseStream: .success(string))
1241
 
1242
                    queue.async {
1243
                        self.capturingError {
1244
                            try stream(.init(event: .stream(.success(string)), token: .init(self)))
1245
                        }
1246
 
1247
                        self.updateAndCompleteIfPossible()
1248
                    }
1249
                }
1250
            }
1251
        }
1252
 
1253
        $streamMutableState.write { $0.streams.append(parser) }
1254
        appendStreamCompletion(on: queue, stream: stream)
1255
 
1256
        return self
1257
    }
1258
 
1259
    private func updateAndCompleteIfPossible() {
1260
        $streamMutableState.write { state in
1261
            state.numberOfExecutingStreams -= 1
1262
 
1263
            guard state.numberOfExecutingStreams == 0, !state.enqueuedCompletionEvents.isEmpty else { return }
1264
 
1265
            let completionEvents = state.enqueuedCompletionEvents
1266
            self.underlyingQueue.async { completionEvents.forEach { $0() } }
1267
            state.enqueuedCompletionEvents.removeAll()
1268
        }
1269
    }
1270
 
1271
    /// Adds a `StreamHandler` which parses incoming `Data` using the provided `DataDecoder`.
1272
    ///
1273
    /// - Parameters:
1274
    ///   - type:         `Decodable` type to parse incoming `Data` into.
1275
    ///   - queue:        `DispatchQueue` on which to perform `StreamHandler` closure.
1276
    ///   - decoder:      `DataDecoder` used to decode the incoming `Data`.
1277
    ///   - preprocessor: `DataPreprocessor` used to process the incoming `Data` before it's passed to the `decoder`.
1278
    ///   - stream:       `StreamHandler` closure called as `Data` is received. May be called multiple times.
1279
    ///
1280
    /// - Returns: The `DataStreamRequest`.
1281
    @discardableResult
1282
    public func responseStreamDecodable<T: Decodable>(of type: T.Type = T.self,
1283
                                                      on queue: DispatchQueue = .main,
1284
                                                      using decoder: DataDecoder = JSONDecoder(),
1285
                                                      preprocessor: DataPreprocessor = PassthroughPreprocessor(),
1286
                                                      stream: @escaping Handler<T, AFError>) -> Self {
1287
        responseStream(using: DecodableStreamSerializer<T>(decoder: decoder, dataPreprocessor: preprocessor),
1288
                       stream: stream)
1289
    }
1290
}