Source/TNLError.h (99 lines of code) (raw):

// // TNLError.h // TwitterNetworkLayer // // Created on 7/17/14. // Copyright © 2020 Twitter. All rights reserved. // #import <Foundation/Foundation.h> @protocol TNLRequestOperationCancelSource; NS_ASSUME_NONNULL_BEGIN FOUNDATION_EXTERN NSErrorDomain const TNLErrorDomain; typedef NSString * const TNLErrorInfoKey NS_STRING_ENUM; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorTimeoutTagsKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorCancelSourceKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorCancelSourceDescriptionKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorCancelSourceLocalizedDescriptionKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorCodeStringKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorHostKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorRequestKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorResponseKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorProtectionSpaceHostKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorCertificateChainDescriptionsKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorAuthenticationChallengeMethodKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorAuthenticationChallengeRealmKey; FOUNDATION_EXTERN TNLErrorInfoKey TNLErrorAuthenticationChallengeCancelContextKey; /** Twitter Network Layer error code ## TNLErrorCodeToString FOUNDATION_EXTERN NSString *TNLErrorCodeToString(TNLErrorCode code); Convert a `TNLErrorCode` to an `NSString` representation ## [NSError domain] for TNL FOUNDATION_EXTERN NSString * const TNLErrorDomain ## [NSError userInfo] keys in TNL // The tags that have been set for active callbacks that were occurring when a timeout occurred FOUNDATION_EXTERN NSString * const TNLErrorTimeoutTagsKey // The source object that caused the `TNLRequestOperation` to cancel FOUNDATION_EXTERN NSString * const TNLErrorCancelSourceKey // The description of the source object that caused the `TNLRequestOperation` to cancel FOUNDATION_EXTERN NSString * const TNLErrorCancelSourceDescriptionKey // The localized and user presentable description of the source object that caused the `TNLRequestOperation` to cancel FOUNDATION_EXTERN NSString * const TNLErrorCancelSourceLocalizedDescriptionKey // A string representation of the `TNLErrorCode` FOUNDATION_EXTERN NSString * const TNLErrorCodeStringKey // The URL's host FOUNDATION_EXTERN NSString * const TNLErrorHostKey ## Helper Macros/Functions TNLErrorCodeIsRequestError(code) // the code is a TNLHTTPRequest error TNLErrorCodeIsRequestOperationError(code) // the code is a TNLRequestOperation error TNLErrorCodeIsGlobalError(code) // the code is a global error TNLErrorCodeIsTerminal(code) // the code is terminal (cannot be retried) ## TNLErrorCode */ typedef NS_ERROR_ENUM(TNLErrorDomain, TNLErrorCode) { /** Unknown error */ TNLErrorCodeUnknown = 0, // Request Error Codes /** Generic `TNLRequest` error */ TNLErrorCodeRequestGenericError = 100, /** Invalid `TNLRequest` */ TNLErrorCodeRequestInvalid = 101, /** Invalid URL on a `TNLRequest` */ TNLErrorCodeRequestInvalidURL = 102, /** Invalid HTTP Method on a `TNLRequest` */ TNLErrorCodeRequestInvalidHTTPMethod = 103, /** When the execution mode is `TNLResponseDataConsumptionModeSaveToDisk`, the HTTP Body must not be set. This is because simultaneous uploading a body and downloading a file is not supported. */ TNLErrorCodeRequestHTTPBodyCannotBeSetForDownload = 104, /** Background requests must either upload data (via file) or download data (to a file). For upload, set an HTTP Body (with `HTTPBodyFilePath`). For download, set the execution mode to `TNLResponseDataConsumptionModeSaveToDisk`. NOTE: background uploading a body without a file (`HTTPBody` or `HTTPBodyStream`) is also invalid and will yield this error. The _NSURLSession_ docs are incorrect, which falsely state that any `NSURLSessionUploadTask` will work on a background session. */ TNLErrorCodeRequestInvalidBackgroundRequest = 105, // Request Operation Error Codes /** Generic `TNLRequestOperation` error */ TNLErrorCodeRequestOperationGenericError = 200, /** The request operation was cancelled. The `NSError` object's `userInfo` will contain a `TNLErrorCancelSourceKey` KVP, a `TNLErrorCancelSourceDescriptionKey` KVP, (optionally) a `TNLErrorCancelSourceLocalizedDescriptionKey` and (optionally) an `NSUnderlyingErrorKey` KVP. See `[TNLRequestOperation cancelWithSource:underlyingError:]` and `[TNLRequestOperationQueue cancelAllWithSource:underlyingError:]`. */ TNLErrorCodeRequestOperationCancelled = 201, /** The request operation timed out. See `[TNLRequestConfiguration operationTimeout]`. */ TNLErrorCodeRequestOperationOperationTimedOut = 202, /** The request attempt timed out. See `[TNLRequestConfiguration attemptTimeout]`. */ TNLErrorCodeRequestOperationAttemptTimedOut = 203, /** The request timed out due to idleness. See `[TNLRequestConfiguration idleTimeout]`. */ TNLErrorCodeRequestOperationIdleTimedOut = 204, /** The request times out due to a delegate/retry-policy callback taking too long (10 seconds). */ TNLErrorCodeRequestOperationCallbackTimedOut = 205, /** The request operation was not provided an object that conforms to the `TNLRequest` protocol. */ TNLErrorCodeRequestOperationRequestNotProvided = 206, /** The `TNLRequest` could not be hydrated. The `NSUnderlyingError` key will be set. */ TNLErrorCodeRequestOperationFailedToHydrateRequest = 207, /** The hydrated `TNLRequest` is not valid. The `NSUnderlyingError` will be set - usually a `TNLErrorCodeRequestBLAH` error. */ TNLErrorCodeRequestOperationInvalidHydratedRequest = 208, /** There was an I/O error */ TNLErrorCodeRequestOperationFileIOError = 209, /** There was an issue appending received data to memory */ TNLErrorCodeRequestOperationAppendResponseDataError = 210, /** The underlying NSURLSession became invalid. If the invalidation is systemic, the `NSUnderlyingError` will be set. */ TNLErrorCodeRequestOperationURLSessionInvalidated = 211, /** Authentication challenge was cancelled */ TNLErrorCodeRequestOperationAuthenticationChallengeCancelled = 212, /** The request's `"Content-Encoding"` HTTP field was specified and it did not match the specified `TNLContentEncoder` on the `TNLRequestConfiguration` */ TNLErrorCodeRequestOperationRequestContentEncodingTypeMissMatch = 213, /** The request's body failed to be encoded with the specified `TNLContentEncoder` on the `TNLRequestConfiguration` */ TNLErrorCodeRequestOperationRequestContentEncodingFailed = 214, /** The response's body failed to be decoded with the matching `TNLContentDecoder` specified by `TNLRequestConfiguration` */ TNLErrorCodeRequestOperationRequestContentDecodingFailed = 215, /** The operation could not authorize its request. */ TNLErrorCodeRequestOperationFailedToAuthorizeRequest = 216, // Global Error Codes /** Generic global error */ TNLErrorCodeGlobalGenericError = 300, /** The URL host was blocked by the `TNLGlobalConfiguration`'s `TNLHostSanitizer`. `TNLErrorHostKey` will be set. */ TNLErrorCodeGlobalHostWasBlocked = 301, // Other Error Codes /** Generic other error */ TNLErrorCodeOtherGenericError = 9900, /** The URL host was empty */ TNLErrorCodeOtherHostCannotBeEmpty = 9901, }; //! Convert `TNLErrorCode` to an `NSString` FOUNDATION_EXTERN NSString * __nullable TNLErrorCodeToString(TNLErrorCode code) NS_SWIFT_NAME(getter:TNLErrorCode.description(self:)); //! Return `YES` if the `TNLErrorCode` is a terminal code and cannot be retried FOUNDATION_EXTERN BOOL TNLErrorCodeIsTerminal(TNLErrorCode code) NS_SWIFT_NAME(getter:TNLErrorCode.isTerminal(self:)); static NSInteger const TNLErrorCodePageSize NS_REFINED_FOR_SWIFT = 100; //! `TNLErrorCode` page size (100 errors per page) NS_SWIFT_NAME(TNLErrorCode.pageSize()) NS_INLINE NSInteger TNLErrorCodeGetPageSize(void) { return TNLErrorCodePageSize; } //! The pages of error codes (100 codes per page max) typedef NS_ENUM(NSInteger, TNLErrorCodePage) { //! Request errors TNLErrorCodePageRequest = (1 * TNLErrorCodePageSize), //! Request operation errors TNLErrorCodePageRequestOperation = (2 * TNLErrorCodePageSize), //! Global __TNL__ errors TNLErrorCodePageGlobal = (3 * TNLErrorCodePageSize), //! Other miscellaneous __TNL__ errors TNLErrorCodePageOther = (99 * TNLErrorCodePageSize) } NS_SWIFT_NAME(TNLErrorCode.Page); //! The error code is a request error NS_SWIFT_NAME(getter:TNLErrorCode.isRequestError(self:)) NS_INLINE BOOL TNLErrorCodeIsRequestError(TNLErrorCode code) { return (((code) / TNLErrorCodePageSize) == (TNLErrorCodePageRequest / TNLErrorCodePageSize)); } //! The error code is a request operation error NS_SWIFT_NAME(getter:TNLErrorCode.isRequestOperationError(self:)) NS_INLINE BOOL TNLErrorCodeIsRequestOperationError(TNLErrorCode code) { return (((code) / TNLErrorCodePageSize) == (TNLErrorCodePageRequestOperation / TNLErrorCodePageSize)); } //! The error code is a global __TNL__ error NS_SWIFT_NAME(getter:TNLErrorCode.isGlobalError(self:)) NS_INLINE BOOL TNLErrorCodeIsGlobalError(TNLErrorCode code) { return (((code) / TNLErrorCodePageSize) == (TNLErrorCodePageGlobal / TNLErrorCodePageSize)); } /** The error code is a request operation timeout error @note Does not include `TNLErrorCodeRequestOperationCallbackTimedOut` because that reflects a client implementation bug of not quickly calling the delegate callback quickly and not an actual networking based timeout firing. */ NS_SWIFT_NAME(getter:TNLErrorCode.isRequestOperationTimeoutError(self:)) NS_INLINE BOOL TNLErrorCodeIsRequestOperationTimeoutError(TNLErrorCode code) { return TNLErrorCodeRequestOperationIdleTimedOut == code || TNLErrorCodeRequestOperationAttemptTimedOut == code || TNLErrorCodeRequestOperationOperationTimedOut == code; } //! Return `YES` if the `NSError` is a network security error, possibly due to Apple's _App Transport Security_ FOUNDATION_EXTERN BOOL TNLErrorIsNetworkSecurityError(NSError * __nullable error); //! Create an `NSError` from a `TNLRequestOperationCancelSource` FOUNDATION_EXTERN NSError * __nonnull TNLErrorFromCancelSource(id<TNLRequestOperationCancelSource> __nullable cancelSource, NSError * __nullable underlyingError); #if APPLEDOC /** A series APIs for dealing with __TNL__ errors. See `TNLErrorCode`. */ @interface TNLError @end #endif #pragma mark - NSError helpers for TNL //! Standard error codes for `NSURLErrorDomain` errors that can be retried FOUNDATION_EXTERN NSArray<NSNumber *> *TNLStandardRetriableURLErrorCodes(void); //! Standard error codes for `NSPOSIXErrorDomain` errors that can be retried FOUNDATION_EXTERN NSArray<NSNumber *> *TNLStandardRetriablePOSIXErrorCodes(void); //! Convert an NSError to be NSSecureCoding safe (strip unsafe values from userInfo). Only returns `nil` if provided _error_ is `nil`. FOUNDATION_EXTERN NSError * __nullable TNLErrorToSecureCodingError(NSError * __nullable error); //! Check if the given NSError objects are equal by just checking their domain+code & underlying errors the same way. Both provided errors being `nil` will also count as being equal. FOUNDATION_EXTERN BOOL TNLSecureCodingErrorsAreEqual(NSError * __nullable error1, NSError * __nullable error2); NS_ASSUME_NONNULL_END