Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  AFError.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
/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
28
/// their own associated reasons.
29
public enum AFError: Error {
30
    /// The underlying reason the `.multipartEncodingFailed` error occurred.
31
    public enum MultipartEncodingFailureReason {
32
        /// The `fileURL` provided for reading an encodable body part isn't a file `URL`.
33
        case bodyPartURLInvalid(url: URL)
34
        /// The filename of the `fileURL` provided has either an empty `lastPathComponent` or `pathExtension.
35
        case bodyPartFilenameInvalid(in: URL)
36
        /// The file at the `fileURL` provided was not reachable.
37
        case bodyPartFileNotReachable(at: URL)
38
        /// Attempting to check the reachability of the `fileURL` provided threw an error.
39
        case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
40
        /// The file at the `fileURL` provided is actually a directory.
41
        case bodyPartFileIsDirectory(at: URL)
42
        /// The size of the file at the `fileURL` provided was not returned by the system.
43
        case bodyPartFileSizeNotAvailable(at: URL)
44
        /// The attempt to find the size of the file at the `fileURL` provided threw an error.
45
        case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
46
        /// An `InputStream` could not be created for the provided `fileURL`.
47
        case bodyPartInputStreamCreationFailed(for: URL)
48
        /// An `OutputStream` could not be created when attempting to write the encoded data to disk.
49
        case outputStreamCreationFailed(for: URL)
50
        /// The encoded body data could not be written to disk because a file already exists at the provided `fileURL`.
51
        case outputStreamFileAlreadyExists(at: URL)
52
        /// The `fileURL` provided for writing the encoded body data to disk is not a file `URL`.
53
        case outputStreamURLInvalid(url: URL)
54
        /// The attempt to write the encoded body data to disk failed with an underlying error.
55
        case outputStreamWriteFailed(error: Error)
56
        /// The attempt to read an encoded body part `InputStream` failed with underlying system error.
57
        case inputStreamReadFailed(error: Error)
58
    }
59
 
60
    /// Represents unexpected input stream length that occur when encoding the `MultipartFormData`. Instances will be
61
    /// embedded within an `AFError.multipartEncodingFailed` `.inputStreamReadFailed` case.
62
    public struct UnexpectedInputStreamLength: Error {
63
        /// The expected byte count to read.
64
        public var bytesExpected: UInt64
65
        /// The actual byte count read.
66
        public var bytesRead: UInt64
67
    }
68
 
69
    /// The underlying reason the `.parameterEncodingFailed` error occurred.
70
    public enum ParameterEncodingFailureReason {
71
        /// The `URLRequest` did not have a `URL` to encode.
72
        case missingURL
73
        /// JSON serialization failed with an underlying system error during the encoding process.
74
        case jsonEncodingFailed(error: Error)
75
        /// Custom parameter encoding failed due to the associated `Error`.
76
        case customEncodingFailed(error: Error)
77
    }
78
 
79
    /// The underlying reason the `.parameterEncoderFailed` error occurred.
80
    public enum ParameterEncoderFailureReason {
81
        /// Possible missing components.
82
        public enum RequiredComponent {
83
            /// The `URL` was missing or unable to be extracted from the passed `URLRequest` or during encoding.
84
            case url
85
            /// The `HTTPMethod` could not be extracted from the passed `URLRequest`.
86
            case httpMethod(rawValue: String)
87
        }
88
 
89
        /// A `RequiredComponent` was missing during encoding.
90
        case missingRequiredComponent(RequiredComponent)
91
        /// The underlying encoder failed with the associated error.
92
        case encoderFailed(error: Error)
93
    }
94
 
95
    /// The underlying reason the `.responseValidationFailed` error occurred.
96
    public enum ResponseValidationFailureReason {
97
        /// The data file containing the server response did not exist.
98
        case dataFileNil
99
        /// The data file containing the server response at the associated `URL` could not be read.
100
        case dataFileReadFailed(at: URL)
101
        /// The response did not contain a `Content-Type` and the `acceptableContentTypes` provided did not contain a
102
        /// wildcard type.
103
        case missingContentType(acceptableContentTypes: [String])
104
        /// The response `Content-Type` did not match any type in the provided `acceptableContentTypes`.
105
        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
106
        /// The response status code was not acceptable.
107
        case unacceptableStatusCode(code: Int)
108
        /// Custom response validation failed due to the associated `Error`.
109
        case customValidationFailed(error: Error)
110
    }
111
 
112
    /// The underlying reason the response serialization error occurred.
113
    public enum ResponseSerializationFailureReason {
114
        /// The server response contained no data or the data was zero length.
115
        case inputDataNilOrZeroLength
116
        /// The file containing the server response did not exist.
117
        case inputFileNil
118
        /// The file containing the server response could not be read from the associated `URL`.
119
        case inputFileReadFailed(at: URL)
120
        /// String serialization failed using the provided `String.Encoding`.
121
        case stringSerializationFailed(encoding: String.Encoding)
122
        /// JSON serialization failed with an underlying system error.
123
        case jsonSerializationFailed(error: Error)
124
        /// A `DataDecoder` failed to decode the response due to the associated `Error`.
125
        case decodingFailed(error: Error)
126
        /// A custom response serializer failed due to the associated `Error`.
127
        case customSerializationFailed(error: Error)
128
        /// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
129
        case invalidEmptyResponse(type: String)
130
    }
131
 
132
    #if !(os(Linux) || os(Windows))
133
    /// Underlying reason a server trust evaluation error occurred.
134
    public enum ServerTrustFailureReason {
135
        /// The output of a server trust evaluation.
136
        public struct Output {
137
            /// The host for which the evaluation was performed.
138
            public let host: String
139
            /// The `SecTrust` value which was evaluated.
140
            public let trust: SecTrust
141
            /// The `OSStatus` of evaluation operation.
142
            public let status: OSStatus
143
            /// The result of the evaluation operation.
144
            public let result: SecTrustResultType
145
 
146
            /// Creates an `Output` value from the provided values.
147
            init(_ host: String, _ trust: SecTrust, _ status: OSStatus, _ result: SecTrustResultType) {
148
                self.host = host
149
                self.trust = trust
150
                self.status = status
151
                self.result = result
152
            }
153
        }
154
 
155
        /// No `ServerTrustEvaluator` was found for the associated host.
156
        case noRequiredEvaluator(host: String)
157
        /// No certificates were found with which to perform the trust evaluation.
158
        case noCertificatesFound
159
        /// No public keys were found with which to perform the trust evaluation.
160
        case noPublicKeysFound
161
        /// During evaluation, application of the associated `SecPolicy` failed.
162
        case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
163
        /// During evaluation, setting the associated anchor certificates failed.
164
        case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
165
        /// During evaluation, creation of the revocation policy failed.
166
        case revocationPolicyCreationFailed
167
        /// `SecTrust` evaluation failed with the associated `Error`, if one was produced.
168
        case trustEvaluationFailed(error: Error?)
169
        /// Default evaluation failed with the associated `Output`.
170
        case defaultEvaluationFailed(output: Output)
171
        /// Host validation failed with the associated `Output`.
172
        case hostValidationFailed(output: Output)
173
        /// Revocation check failed with the associated `Output` and options.
174
        case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
175
        /// Certificate pinning failed.
176
        case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
177
        /// Public key pinning failed.
178
        case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
179
        /// Custom server trust evaluation failed due to the associated `Error`.
180
        case customEvaluationFailed(error: Error)
181
    }
182
    #endif
183
 
184
    /// The underlying reason the `.urlRequestValidationFailed`
185
    public enum URLRequestValidationFailureReason {
186
        /// URLRequest with GET method had body data.
187
        case bodyDataInGETRequest(Data)
188
    }
189
 
190
    ///  `UploadableConvertible` threw an error in `createUploadable()`.
191
    case createUploadableFailed(error: Error)
192
    ///  `URLRequestConvertible` threw an error in `asURLRequest()`.
193
    case createURLRequestFailed(error: Error)
194
    /// `SessionDelegate` threw an error while attempting to move downloaded file to destination URL.
195
    case downloadedFileMoveFailed(error: Error, source: URL, destination: URL)
196
    /// `Request` was explicitly cancelled.
197
    case explicitlyCancelled
198
    /// `URLConvertible` type failed to create a valid `URL`.
199
    case invalidURL(url: URLConvertible)
200
    /// Multipart form encoding failed.
201
    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
202
    /// `ParameterEncoding` threw an error during the encoding process.
203
    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
204
    /// `ParameterEncoder` threw an error while running the encoder.
205
    case parameterEncoderFailed(reason: ParameterEncoderFailureReason)
206
    /// `RequestAdapter` threw an error during adaptation.
207
    case requestAdaptationFailed(error: Error)
208
    /// `RequestRetrier` threw an error during the request retry process.
209
    case requestRetryFailed(retryError: Error, originalError: Error)
210
    /// Response validation failed.
211
    case responseValidationFailed(reason: ResponseValidationFailureReason)
212
    /// Response serialization failed.
213
    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
214
    #if !(os(Linux) || os(Windows))
215
    /// `ServerTrustEvaluating` instance threw an error during trust evaluation.
216
    case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
217
    #endif
218
    /// `Session` which issued the `Request` was deinitialized, most likely because its reference went out of scope.
219
    case sessionDeinitialized
220
    /// `Session` was explicitly invalidated, possibly with the `Error` produced by the underlying `URLSession`.
221
    case sessionInvalidated(error: Error?)
222
    /// `URLSessionTask` completed with error.
223
    case sessionTaskFailed(error: Error)
224
    /// `URLRequest` failed validation.
225
    case urlRequestValidationFailed(reason: URLRequestValidationFailureReason)
226
}
227
 
228
extension Error {
229
    /// Returns the instance cast as an `AFError`.
230
    public var asAFError: AFError? {
231
        self as? AFError
232
    }
233
 
234
    /// Returns the instance cast as an `AFError`. If casting fails, a `fatalError` with the specified `message` is thrown.
235
    public func asAFError(orFailWith message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) -> AFError {
236
        guard let afError = self as? AFError else {
237
            fatalError(message(), file: file, line: line)
238
        }
239
        return afError
240
    }
241
 
242
    /// Casts the instance as `AFError` or returns `defaultAFError`
243
    func asAFError(or defaultAFError: @autoclosure () -> AFError) -> AFError {
244
        self as? AFError ?? defaultAFError()
245
    }
246
}
247
 
248
// MARK: - Error Booleans
249
 
250
extension AFError {
251
    /// Returns whether the instance is `.sessionDeinitialized`.
252
    public var isSessionDeinitializedError: Bool {
253
        if case .sessionDeinitialized = self { return true }
254
        return false
255
    }
256
 
257
    /// Returns whether the instance is `.sessionInvalidated`.
258
    public var isSessionInvalidatedError: Bool {
259
        if case .sessionInvalidated = self { return true }
260
        return false
261
    }
262
 
263
    /// Returns whether the instance is `.explicitlyCancelled`.
264
    public var isExplicitlyCancelledError: Bool {
265
        if case .explicitlyCancelled = self { return true }
266
        return false
267
    }
268
 
269
    /// Returns whether the instance is `.invalidURL`.
270
    public var isInvalidURLError: Bool {
271
        if case .invalidURL = self { return true }
272
        return false
273
    }
274
 
275
    /// Returns whether the instance is `.parameterEncodingFailed`. When `true`, the `underlyingError` property will
276
    /// contain the associated value.
277
    public var isParameterEncodingError: Bool {
278
        if case .parameterEncodingFailed = self { return true }
279
        return false
280
    }
281
 
282
    /// Returns whether the instance is `.parameterEncoderFailed`. When `true`, the `underlyingError` property will
283
    /// contain the associated value.
284
    public var isParameterEncoderError: Bool {
285
        if case .parameterEncoderFailed = self { return true }
286
        return false
287
    }
288
 
289
    /// Returns whether the instance is `.multipartEncodingFailed`. When `true`, the `url` and `underlyingError`
290
    /// properties will contain the associated values.
291
    public var isMultipartEncodingError: Bool {
292
        if case .multipartEncodingFailed = self { return true }
293
        return false
294
    }
295
 
296
    /// Returns whether the instance is `.requestAdaptationFailed`. When `true`, the `underlyingError` property will
297
    /// contain the associated value.
298
    public var isRequestAdaptationError: Bool {
299
        if case .requestAdaptationFailed = self { return true }
300
        return false
301
    }
302
 
303
    /// Returns whether the instance is `.responseValidationFailed`. When `true`, the `acceptableContentTypes`,
304
    /// `responseContentType`,  `responseCode`, and `underlyingError` properties will contain the associated values.
305
    public var isResponseValidationError: Bool {
306
        if case .responseValidationFailed = self { return true }
307
        return false
308
    }
309
 
310
    /// Returns whether the instance is `.responseSerializationFailed`. When `true`, the `failedStringEncoding` and
311
    /// `underlyingError` properties will contain the associated values.
312
    public var isResponseSerializationError: Bool {
313
        if case .responseSerializationFailed = self { return true }
314
        return false
315
    }
316
 
317
    #if !(os(Linux) || os(Windows))
318
    /// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
319
    /// contain the associated value.
320
    public var isServerTrustEvaluationError: Bool {
321
        if case .serverTrustEvaluationFailed = self { return true }
322
        return false
323
    }
324
    #endif
325
 
326
    /// Returns whether the instance is `requestRetryFailed`. When `true`, the `underlyingError` property will
327
    /// contain the associated value.
328
    public var isRequestRetryError: Bool {
329
        if case .requestRetryFailed = self { return true }
330
        return false
331
    }
332
 
333
    /// Returns whether the instance is `createUploadableFailed`. When `true`, the `underlyingError` property will
334
    /// contain the associated value.
335
    public var isCreateUploadableError: Bool {
336
        if case .createUploadableFailed = self { return true }
337
        return false
338
    }
339
 
340
    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
341
    /// contain the associated value.
342
    public var isCreateURLRequestError: Bool {
343
        if case .createURLRequestFailed = self { return true }
344
        return false
345
    }
346
 
347
    /// Returns whether the instance is `downloadedFileMoveFailed`. When `true`, the `destination` and `underlyingError` properties will
348
    /// contain the associated values.
349
    public var isDownloadedFileMoveError: Bool {
350
        if case .downloadedFileMoveFailed = self { return true }
351
        return false
352
    }
353
 
354
    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
355
    /// contain the associated value.
356
    public var isSessionTaskError: Bool {
357
        if case .sessionTaskFailed = self { return true }
358
        return false
359
    }
360
}
361
 
362
// MARK: - Convenience Properties
363
 
364
extension AFError {
365
    /// The `URLConvertible` associated with the error.
366
    public var urlConvertible: URLConvertible? {
367
        guard case let .invalidURL(url) = self else { return nil }
368
        return url
369
    }
370
 
371
    /// The `URL` associated with the error.
372
    public var url: URL? {
373
        guard case let .multipartEncodingFailed(reason) = self else { return nil }
374
        return reason.url
375
    }
376
 
377
    /// The underlying `Error` responsible for generating the failure associated with `.sessionInvalidated`,
378
    /// `.parameterEncodingFailed`, `.parameterEncoderFailed`, `.multipartEncodingFailed`, `.requestAdaptationFailed`,
379
    /// `.responseSerializationFailed`, `.requestRetryFailed` errors.
380
    public var underlyingError: Error? {
381
        switch self {
382
        case let .multipartEncodingFailed(reason):
383
            return reason.underlyingError
384
        case let .parameterEncodingFailed(reason):
385
            return reason.underlyingError
386
        case let .parameterEncoderFailed(reason):
387
            return reason.underlyingError
388
        case let .requestAdaptationFailed(error):
389
            return error
390
        case let .requestRetryFailed(retryError, _):
391
            return retryError
392
        case let .responseValidationFailed(reason):
393
            return reason.underlyingError
394
        case let .responseSerializationFailed(reason):
395
            return reason.underlyingError
396
        #if !(os(Linux) || os(Windows))
397
        case let .serverTrustEvaluationFailed(reason):
398
            return reason.underlyingError
399
        #endif
400
        case let .sessionInvalidated(error):
401
            return error
402
        case let .createUploadableFailed(error):
403
            return error
404
        case let .createURLRequestFailed(error):
405
            return error
406
        case let .downloadedFileMoveFailed(error, _, _):
407
            return error
408
        case let .sessionTaskFailed(error):
409
            return error
410
        case .explicitlyCancelled,
411
             .invalidURL,
412
             .sessionDeinitialized,
413
             .urlRequestValidationFailed:
414
            return nil
415
        }
416
    }
417
 
418
    /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
419
    public var acceptableContentTypes: [String]? {
420
        guard case let .responseValidationFailed(reason) = self else { return nil }
421
        return reason.acceptableContentTypes
422
    }
423
 
424
    /// The response `Content-Type` of a `.responseValidationFailed` error.
425
    public var responseContentType: String? {
426
        guard case let .responseValidationFailed(reason) = self else { return nil }
427
        return reason.responseContentType
428
    }
429
 
430
    /// The response code of a `.responseValidationFailed` error.
431
    public var responseCode: Int? {
432
        guard case let .responseValidationFailed(reason) = self else { return nil }
433
        return reason.responseCode
434
    }
435
 
436
    /// The `String.Encoding` associated with a failed `.stringResponse()` call.
437
    public var failedStringEncoding: String.Encoding? {
438
        guard case let .responseSerializationFailed(reason) = self else { return nil }
439
        return reason.failedStringEncoding
440
    }
441
 
442
    /// The `source` URL of a `.downloadedFileMoveFailed` error.
443
    public var sourceURL: URL? {
444
        guard case let .downloadedFileMoveFailed(_, source, _) = self else { return nil }
445
        return source
446
    }
447
 
448
    /// The `destination` URL of a `.downloadedFileMoveFailed` error.
449
    public var destinationURL: URL? {
450
        guard case let .downloadedFileMoveFailed(_, _, destination) = self else { return nil }
451
        return destination
452
    }
453
 
454
    #if !(os(Linux) || os(Windows))
455
    /// The download resume data of any underlying network error. Only produced by `DownloadRequest`s.
456
    public var downloadResumeData: Data? {
457
        (underlyingError as? URLError)?.userInfo[NSURLSessionDownloadTaskResumeData] as? Data
458
    }
459
    #endif
460
}
461
 
462
extension AFError.ParameterEncodingFailureReason {
463
    var underlyingError: Error? {
464
        switch self {
465
        case let .jsonEncodingFailed(error),
466
             let .customEncodingFailed(error):
467
            return error
468
        case .missingURL:
469
            return nil
470
        }
471
    }
472
}
473
 
474
extension AFError.ParameterEncoderFailureReason {
475
    var underlyingError: Error? {
476
        switch self {
477
        case let .encoderFailed(error):
478
            return error
479
        case .missingRequiredComponent:
480
            return nil
481
        }
482
    }
483
}
484
 
485
extension AFError.MultipartEncodingFailureReason {
486
    var url: URL? {
487
        switch self {
488
        case let .bodyPartURLInvalid(url),
489
             let .bodyPartFilenameInvalid(url),
490
             let .bodyPartFileNotReachable(url),
491
             let .bodyPartFileIsDirectory(url),
492
             let .bodyPartFileSizeNotAvailable(url),
493
             let .bodyPartInputStreamCreationFailed(url),
494
             let .outputStreamCreationFailed(url),
495
             let .outputStreamFileAlreadyExists(url),
496
             let .outputStreamURLInvalid(url),
497
             let .bodyPartFileNotReachableWithError(url, _),
498
             let .bodyPartFileSizeQueryFailedWithError(url, _):
499
            return url
500
        case .outputStreamWriteFailed,
501
             .inputStreamReadFailed:
502
            return nil
503
        }
504
    }
505
 
506
    var underlyingError: Error? {
507
        switch self {
508
        case let .bodyPartFileNotReachableWithError(_, error),
509
             let .bodyPartFileSizeQueryFailedWithError(_, error),
510
             let .outputStreamWriteFailed(error),
511
             let .inputStreamReadFailed(error):
512
            return error
513
        case .bodyPartURLInvalid,
514
             .bodyPartFilenameInvalid,
515
             .bodyPartFileNotReachable,
516
             .bodyPartFileIsDirectory,
517
             .bodyPartFileSizeNotAvailable,
518
             .bodyPartInputStreamCreationFailed,
519
             .outputStreamCreationFailed,
520
             .outputStreamFileAlreadyExists,
521
             .outputStreamURLInvalid:
522
            return nil
523
        }
524
    }
525
}
526
 
527
extension AFError.ResponseValidationFailureReason {
528
    var acceptableContentTypes: [String]? {
529
        switch self {
530
        case let .missingContentType(types),
531
             let .unacceptableContentType(types, _):
532
            return types
533
        case .dataFileNil,
534
             .dataFileReadFailed,
535
             .unacceptableStatusCode,
536
             .customValidationFailed:
537
            return nil
538
        }
539
    }
540
 
541
    var responseContentType: String? {
542
        switch self {
543
        case let .unacceptableContentType(_, responseType):
544
            return responseType
545
        case .dataFileNil,
546
             .dataFileReadFailed,
547
             .missingContentType,
548
             .unacceptableStatusCode,
549
             .customValidationFailed:
550
            return nil
551
        }
552
    }
553
 
554
    var responseCode: Int? {
555
        switch self {
556
        case let .unacceptableStatusCode(code):
557
            return code
558
        case .dataFileNil,
559
             .dataFileReadFailed,
560
             .missingContentType,
561
             .unacceptableContentType,
562
             .customValidationFailed:
563
            return nil
564
        }
565
    }
566
 
567
    var underlyingError: Error? {
568
        switch self {
569
        case let .customValidationFailed(error):
570
            return error
571
        case .dataFileNil,
572
             .dataFileReadFailed,
573
             .missingContentType,
574
             .unacceptableContentType,
575
             .unacceptableStatusCode:
576
            return nil
577
        }
578
    }
579
}
580
 
581
extension AFError.ResponseSerializationFailureReason {
582
    var failedStringEncoding: String.Encoding? {
583
        switch self {
584
        case let .stringSerializationFailed(encoding):
585
            return encoding
586
        case .inputDataNilOrZeroLength,
587
             .inputFileNil,
588
             .inputFileReadFailed(_),
589
             .jsonSerializationFailed(_),
590
             .decodingFailed(_),
591
             .customSerializationFailed(_),
592
             .invalidEmptyResponse:
593
            return nil
594
        }
595
    }
596
 
597
    var underlyingError: Error? {
598
        switch self {
599
        case let .jsonSerializationFailed(error),
600
             let .decodingFailed(error),
601
             let .customSerializationFailed(error):
602
            return error
603
        case .inputDataNilOrZeroLength,
604
             .inputFileNil,
605
             .inputFileReadFailed,
606
             .stringSerializationFailed,
607
             .invalidEmptyResponse:
608
            return nil
609
        }
610
    }
611
}
612
 
613
#if !(os(Linux) || os(Windows))
614
extension AFError.ServerTrustFailureReason {
615
    var output: AFError.ServerTrustFailureReason.Output? {
616
        switch self {
617
        case let .defaultEvaluationFailed(output),
618
             let .hostValidationFailed(output),
619
             let .revocationCheckFailed(output, _):
620
            return output
621
        case .noRequiredEvaluator,
622
             .noCertificatesFound,
623
             .noPublicKeysFound,
624
             .policyApplicationFailed,
625
             .settingAnchorCertificatesFailed,
626
             .revocationPolicyCreationFailed,
627
             .trustEvaluationFailed,
628
             .certificatePinningFailed,
629
             .publicKeyPinningFailed,
630
             .customEvaluationFailed:
631
            return nil
632
        }
633
    }
634
 
635
    var underlyingError: Error? {
636
        switch self {
637
        case let .customEvaluationFailed(error):
638
            return error
639
        case let .trustEvaluationFailed(error):
640
            return error
641
        case .noRequiredEvaluator,
642
             .noCertificatesFound,
643
             .noPublicKeysFound,
644
             .policyApplicationFailed,
645
             .settingAnchorCertificatesFailed,
646
             .revocationPolicyCreationFailed,
647
             .defaultEvaluationFailed,
648
             .hostValidationFailed,
649
             .revocationCheckFailed,
650
             .certificatePinningFailed,
651
             .publicKeyPinningFailed:
652
            return nil
653
        }
654
    }
655
}
656
#endif
657
 
658
// MARK: - Error Descriptions
659
 
660
extension AFError: LocalizedError {
661
    public var errorDescription: String? {
662
        switch self {
663
        case .explicitlyCancelled:
664
            return "Request explicitly cancelled."
665
        case let .invalidURL(url):
666
            return "URL is not valid: \(url)"
667
        case let .parameterEncodingFailed(reason):
668
            return reason.localizedDescription
669
        case let .parameterEncoderFailed(reason):
670
            return reason.localizedDescription
671
        case let .multipartEncodingFailed(reason):
672
            return reason.localizedDescription
673
        case let .requestAdaptationFailed(error):
674
            return "Request adaption failed with error: \(error.localizedDescription)"
675
        case let .responseValidationFailed(reason):
676
            return reason.localizedDescription
677
        case let .responseSerializationFailed(reason):
678
            return reason.localizedDescription
679
        case let .requestRetryFailed(retryError, originalError):
680
            return """
681
            Request retry failed with retry error: \(retryError.localizedDescription), \
682
            original error: \(originalError.localizedDescription)
683
            """
684
        case .sessionDeinitialized:
685
            return """
686
            Session was invalidated without error, so it was likely deinitialized unexpectedly. \
687
            Be sure to retain a reference to your Session for the duration of your requests.
688
            """
689
        case let .sessionInvalidated(error):
690
            return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
691
        #if !(os(Linux) || os(Windows))
692
        case let .serverTrustEvaluationFailed(reason):
693
            return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
694
        #endif
695
        case let .urlRequestValidationFailed(reason):
696
            return "URLRequest validation failed due to reason: \(reason.localizedDescription)"
697
        case let .createUploadableFailed(error):
698
            return "Uploadable creation failed with error: \(error.localizedDescription)"
699
        case let .createURLRequestFailed(error):
700
            return "URLRequest creation failed with error: \(error.localizedDescription)"
701
        case let .downloadedFileMoveFailed(error, source, destination):
702
            return "Moving downloaded file from: \(source) to: \(destination) failed with error: \(error.localizedDescription)"
703
        case let .sessionTaskFailed(error):
704
            return "URLSessionTask failed with error: \(error.localizedDescription)"
705
        }
706
    }
707
}
708
 
709
extension AFError.ParameterEncodingFailureReason {
710
    var localizedDescription: String {
711
        switch self {
712
        case .missingURL:
713
            return "URL request to encode was missing a URL"
714
        case let .jsonEncodingFailed(error):
715
            return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
716
        case let .customEncodingFailed(error):
717
            return "Custom parameter encoder failed with error: \(error.localizedDescription)"
718
        }
719
    }
720
}
721
 
722
extension AFError.ParameterEncoderFailureReason {
723
    var localizedDescription: String {
724
        switch self {
725
        case let .missingRequiredComponent(component):
726
            return "Encoding failed due to a missing request component: \(component)"
727
        case let .encoderFailed(error):
728
            return "The underlying encoder failed with the error: \(error)"
729
        }
730
    }
731
}
732
 
733
extension AFError.MultipartEncodingFailureReason {
734
    var localizedDescription: String {
735
        switch self {
736
        case let .bodyPartURLInvalid(url):
737
            return "The URL provided is not a file URL: \(url)"
738
        case let .bodyPartFilenameInvalid(url):
739
            return "The URL provided does not have a valid filename: \(url)"
740
        case let .bodyPartFileNotReachable(url):
741
            return "The URL provided is not reachable: \(url)"
742
        case let .bodyPartFileNotReachableWithError(url, error):
743
            return """
744
            The system returned an error while checking the provided URL for reachability.
745
            URL: \(url)
746
            Error: \(error)
747
            """
748
        case let .bodyPartFileIsDirectory(url):
749
            return "The URL provided is a directory: \(url)"
750
        case let .bodyPartFileSizeNotAvailable(url):
751
            return "Could not fetch the file size from the provided URL: \(url)"
752
        case let .bodyPartFileSizeQueryFailedWithError(url, error):
753
            return """
754
            The system returned an error while attempting to fetch the file size from the provided URL.
755
            URL: \(url)
756
            Error: \(error)
757
            """
758
        case let .bodyPartInputStreamCreationFailed(url):
759
            return "Failed to create an InputStream for the provided URL: \(url)"
760
        case let .outputStreamCreationFailed(url):
761
            return "Failed to create an OutputStream for URL: \(url)"
762
        case let .outputStreamFileAlreadyExists(url):
763
            return "A file already exists at the provided URL: \(url)"
764
        case let .outputStreamURLInvalid(url):
765
            return "The provided OutputStream URL is invalid: \(url)"
766
        case let .outputStreamWriteFailed(error):
767
            return "OutputStream write failed with error: \(error)"
768
        case let .inputStreamReadFailed(error):
769
            return "InputStream read failed with error: \(error)"
770
        }
771
    }
772
}
773
 
774
extension AFError.ResponseSerializationFailureReason {
775
    var localizedDescription: String {
776
        switch self {
777
        case .inputDataNilOrZeroLength:
778
            return "Response could not be serialized, input data was nil or zero length."
779
        case .inputFileNil:
780
            return "Response could not be serialized, input file was nil."
781
        case let .inputFileReadFailed(url):
782
            return "Response could not be serialized, input file could not be read: \(url)."
783
        case let .stringSerializationFailed(encoding):
784
            return "String could not be serialized with encoding: \(encoding)."
785
        case let .jsonSerializationFailed(error):
786
            return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
787
        case let .invalidEmptyResponse(type):
788
            return """
789
            Empty response could not be serialized to type: \(type). \
790
            Use Empty as the expected type for such responses.
791
            """
792
        case let .decodingFailed(error):
793
            return "Response could not be decoded because of error:\n\(error.localizedDescription)"
794
        case let .customSerializationFailed(error):
795
            return "Custom response serializer failed with error:\n\(error.localizedDescription)"
796
        }
797
    }
798
}
799
 
800
extension AFError.ResponseValidationFailureReason {
801
    var localizedDescription: String {
802
        switch self {
803
        case .dataFileNil:
804
            return "Response could not be validated, data file was nil."
805
        case let .dataFileReadFailed(url):
806
            return "Response could not be validated, data file could not be read: \(url)."
807
        case let .missingContentType(types):
808
            return """
809
            Response Content-Type was missing and acceptable content types \
810
            (\(types.joined(separator: ","))) do not match "*/*".
811
            """
812
        case let .unacceptableContentType(acceptableTypes, responseType):
813
            return """
814
            Response Content-Type "\(responseType)" does not match any acceptable types: \
815
            \(acceptableTypes.joined(separator: ",")).
816
            """
817
        case let .unacceptableStatusCode(code):
818
            return "Response status code was unacceptable: \(code)."
819
        case let .customValidationFailed(error):
820
            return "Custom response validation failed with error: \(error.localizedDescription)"
821
        }
822
    }
823
}
824
 
825
#if !(os(Linux) || os(Windows))
826
extension AFError.ServerTrustFailureReason {
827
    var localizedDescription: String {
828
        switch self {
829
        case let .noRequiredEvaluator(host):
830
            return "A ServerTrustEvaluating value is required for host \(host) but none was found."
831
        case .noCertificatesFound:
832
            return "No certificates were found or provided for evaluation."
833
        case .noPublicKeysFound:
834
            return "No public keys were found or provided for evaluation."
835
        case .policyApplicationFailed:
836
            return "Attempting to set a SecPolicy failed."
837
        case .settingAnchorCertificatesFailed:
838
            return "Attempting to set the provided certificates as anchor certificates failed."
839
        case .revocationPolicyCreationFailed:
840
            return "Attempting to create a revocation policy failed."
841
        case let .trustEvaluationFailed(error):
842
            return "SecTrust evaluation failed with error: \(error?.localizedDescription ?? "None")"
843
        case let .defaultEvaluationFailed(output):
844
            return "Default evaluation failed for host \(output.host)."
845
        case let .hostValidationFailed(output):
846
            return "Host validation failed for host \(output.host)."
847
        case let .revocationCheckFailed(output, _):
848
            return "Revocation check failed for host \(output.host)."
849
        case let .certificatePinningFailed(host, _, _, _):
850
            return "Certificate pinning failed for host \(host)."
851
        case let .publicKeyPinningFailed(host, _, _, _):
852
            return "Public key pinning failed for host \(host)."
853
        case let .customEvaluationFailed(error):
854
            return "Custom trust evaluation failed with error: \(error.localizedDescription)"
855
        }
856
    }
857
}
858
#endif
859
 
860
extension AFError.URLRequestValidationFailureReason {
861
    var localizedDescription: String {
862
        switch self {
863
        case let .bodyDataInGETRequest(data):
864
            return """
865
            Invalid URLRequest: Requests with GET method cannot have body data:
866
            \(String(decoding: data, as: UTF8.self))
867
            """
868
        }
869
    }
870
}