Source/TNLHTTP.h (193 lines of code) (raw):

// // TNLHTTP.h // TwitterNetworkLayer // // Created on 6/9/14. // Copyright © 2020 Twitter. All rights reserved. // #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN #pragma mark - HTTP Method /** TNLHTTPMethod # HTTP Methods HTTP methods per http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html Values correspond to the subsection number of Section 9 in RFC 2616. Ex: GET is Section 9.3 ## Helper Functions // Convert TNLHTTPMethod to an NSString (ex: TNLHTTPMethodGET -> @"GET"). // Unknown values will return nil. FOUNDATION_EXTERN NSString *TNLHTTPMethodToString(TNLHTTPMethod method); // Convert an NSString to TNLHTTPMethod (ex: @"GET" -> TNLHTTPMethodGET). // Unknown strings will return TNLHTTPMethodUnknown. FOUNDATION_EXTERN TNLHTTPMethod TNLHTTPMethodFromString(NSString *methodString); */ typedef NS_ENUM(NSInteger, TNLHTTPMethod) { TNLHTTPMethodUnknown = 0, TNLHTTPMethodOPTIONS = 2, TNLHTTPMethodGET = 3, TNLHTTPMethodHEAD = 4, TNLHTTPMethodPOST = 5, TNLHTTPMethodPUT = 6, TNLHTTPMethodDELETE = 7, TNLHTTPMethodTRACE = 8, TNLHTTPMethodCONNECT = 9 }; FOUNDATION_EXTERN NSString * __nullable TNLHTTPMethodToString(TNLHTTPMethod method) NS_SWIFT_NAME(getter:TNLHTTPMethod.description(self:)); FOUNDATION_EXTERN TNLHTTPMethod TNLHTTPMethodFromString(NSString *methodString) NS_SWIFT_NAME(TNLHTTPMethod.init(method:)); #pragma mark - HTTP Status Code /** TNLHTTPStatusCode # HTTP Status Codes `TNLHTTPStatusCode` is ONLY for HTTP status codes. Do not introduce any non-HTTP status codes to this enum. The values are composed primarily from HTTP 1.1 RFC 2616 (section 10) http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html but also contain values that are not ratified from @link http://en.wikipedia.org/wiki/List_of_HTTP_status_codes ## Helper Macros TNLHTTPStatusCodeIsInformational(code) // YES if the code is informational (1xx) TNLHTTPStatusCodeIsSuccess(code) // YES if the code is success (2xx) TNLHTTPStatusCodeIsRedirection(code) // YES if the code is redirect (3xx) TNLHTTPStatusCodeIsClientError(code) // YES if the code is client error (4xx) TNLHTTPStatusCodeIsServerError(code) // YES if the code is server error (5xx) */ typedef NS_ENUM(NSInteger, TNLHTTPStatusCode) { // 0 == None TNLHTTPStatusCodeNone = 0, // 1xx Informational TNLHTTPStatusCodeContinue = 100, TNLHTTPStatusCodeSwitchingProtocols = 101, TNLHTTPStatusCodeProcessing = 102, TNLHTTPStatusCodeCheckpoint = 103, // 2xx Success TNLHTTPStatusCodeOK = 200, TNLHTTPStatusCodeCreated = 201, TNLHTTPStatusCodeAccepted = 202, TNLHTTPStatusCodeNonAuthoritativeInformation = 203, TNLHTTPStatusCodeNoContent = 204, TNLHTTPStatusCodeResetContent = 205, TNLHTTPStatusCodePartialContent = 206, TNLHTTPStatusCodeMultiStatus = 207, TNLHTTPStatusCodeAlreadyReported = 208, TNLHTTPStatusCodeInstanceManipulationUsed = 226, // 3xx Redirection TNLHTTPStatusCodeMultipleChoices = 300, TNLHTTPStatusCodeMovedPermanently = 301, TNLHTTPStatusCodeFound = 302, TNLHTTPStatusCodeSeeOther = 303, TNLHTTPStatusCodeNotModified = 304, TNLHTTPStatusCodeUseProxy = 305, TNLHTTPStatusCodeSwitchProxy = 306, TNLHTTPStatusCodeTemporaryRedirect = 307, TNLHTTPStatusCodePermanentRedirect = 308, // 4xx Client Error TNLHTTPStatusCodeBadRequest = 400, TNLHTTPStatusCodeUnauthorized = 401, TNLHTTPStatusCodePaymentRequired = 402, // <<-- man I hope this never goes into effect TNLHTTPStatusCodeForbidden = 403, TNLHTTPStatusCodeNotFound = 404, TNLHTTPStatusCodeMethodNotAllowed = 405, TNLHTTPStatusCodeNotAcceptable = 406, TNLHTTPStatusCodeProxyAuthenticationRequired = 407, TNLHTTPStatusCodeRequestTimeout = 408, TNLHTTPStatusCodeConflict = 409, TNLHTTPStatusCodeGone = 410, TNLHTTPStatusCodeLengthRequired = 411, TNLHTTPStatusCodePreconditionFailed = 412, TNLHTTPStatusCodeRequestEntityTooLarge = 413, TNLHTTPStatusCodeRequestURITooLong = 414, TNLHTTPStatusCodeUnsupportedMediaType = 415, TNLHTTPStatusCodeRequestedRangeNotSatisfiable = 416, TNLHTTPStatusCodeExpectationFailed = 417, TNLHTTPStatusCodeImATeapot = 418, // <-- April Fool's TNLHTTPStatusCodeAuthenticationTimeout = 419, TNLHTTPStatusCodeEnhanceYourCalm = 420, // <-- the old 'Twitter' way for a 429 TNLHTTPStatusCodeMisdirectedRequest = 421, TNLHTTPStatusCodeUnprocessableEntity = 422, TNLHTTPStatusCodeLocked = 423, TNLHTTPStatusCodeFailedDependency = 424, TNLHTTPStatusCodeUnorderedCollection = 425, TNLHTTPStatusCodeUpgradeRequired = 426, TNLHTTPStatusCodePreconditionRequired = 428, TNLHTTPStatusCodeTooManyRequests = 429, TNLHTTPStatusCodeRequestHeaderFieldsTooLarge = 431, TNLHTTPStatusCodeLoginTimeout = 440, TNLHTTPStatusCodeNoResponse = 444, TNLHTTPStatusCodeRetryWith = 449, /* retry with the missing required info */ TNLHTTPStatusCodeBlockedByParentalControls = 450, /* Windows only a.t.m. */ TNLHTTPStatusCodeUnavailableForLegalReasons = 451, /* Fahrenheit 451 */ TNLHTTPStatusCodeSSLCertificateError = 495, TNLHTTPStatusCodeSSLCertificateRequired = 496, TNLHTTPStatusCodeHTTPRequestSentToHTTPSPort = 497, TNLHTTPStatusCodeInvalidToken = 498, TNLHTTPStatusCodeClientClosedRequest = 499, // 5xx Server Error TNLHTTPStatusCodeInternalServerError = 500, TNLHTTPStatusCodeNotImplemented = 501, TNLHTTPStatusCodeBadGateway = 502, TNLHTTPStatusCodeServiceUnavailable = 503, TNLHTTPStatusCodeGatewayTimeout = 504, TNLHTTPStatusCodeHTTPVersionNotSupported = 505, TNLHTTPStatusCodeVariantAlsoNegotiates = 506, TNLHTTPStatusCodeInsufficientStorage = 507, TNLHTTPStatusCodeLoopDetected = 508, TNLHTTPStatusCodeBandwidthLimitExceeded = 509, TNLHTTPStatusCodeNotExtended = 510, TNLHTTPStatusCodeNetworkAuthenticationRequired = 511, TNLHTTPStatusCodeUnknownError = 520, // Cloudflare TNLHTTPStatusCodeWebServerIsDown = 521, // Cloudflare TNLHTTPStatusCodeConnectionTimedOut = 522, // Cloudflare TNLHTTPStatusCodeOriginIsUnreachable = 523, // Cloudflare TNLHTTPStatusCodeATimeoutOccurred = 524, // Cloudflare TNLHTTPStatusCodeSSLHandshakeFailed = 525, // Cloudflare TNLHTTPStatusCodeInvalidSSLCertificate = 526, // Cloudflare TNLHTTPStatusCodeRailgunError = 527, // Cloudflare TNLHTTPStatusCodeSiteIsFrozen = 530, TNLHTTPStatusCodeNetworkReadTimeout = 598, }; #define TNLHTTPStatusCodePageInformational (100) #define TNLHTTPStatusCodePageSuccess (200) #define TNLHTTPStatusCodePageRedirection (300) #define TNLHTTPStatusCodePageClientError (400) #define TNLHTTPStatusCodePageServerError (500) #define TNLHTTPStatusCodePageSize (100) //! HTTP 1xx NS_SWIFT_NAME(getter:TNLHTTPStatusCode.isInformational(self:)) NS_INLINE BOOL TNLHTTPStatusCodeIsInformational(TNLHTTPStatusCode code) { return (code / TNLHTTPStatusCodePageSize) == (TNLHTTPStatusCodePageInformational / TNLHTTPStatusCodePageSize); } //! HTTP 2xx NS_SWIFT_NAME(getter:TNLHTTPStatusCode.isSuccess(self:)) NS_INLINE BOOL TNLHTTPStatusCodeIsSuccess(TNLHTTPStatusCode code) { return (code / TNLHTTPStatusCodePageSize) == (TNLHTTPStatusCodePageSuccess / TNLHTTPStatusCodePageSize); } //! HTTP 3xx NS_SWIFT_NAME(getter:TNLHTTPStatusCode.isRedirection(self:)) NS_INLINE BOOL TNLHTTPStatusCodeIsRedirection(TNLHTTPStatusCode code) { return (code / TNLHTTPStatusCodePageSize) == (TNLHTTPStatusCodePageRedirection / TNLHTTPStatusCodePageSize); } //! HTTP 4xx NS_SWIFT_NAME(getter:TNLHTTPStatusCode.isClientError(self:)) NS_INLINE BOOL TNLHTTPStatusCodeIsClientError(TNLHTTPStatusCode code) { return (code / TNLHTTPStatusCodePageSize) == (TNLHTTPStatusCodePageClientError / TNLHTTPStatusCodePageSize); } //! HTTP 5xx NS_SWIFT_NAME(getter:TNLHTTPStatusCode.isServerError(self:)) NS_INLINE BOOL TNLHTTPStatusCodeIsServerError(TNLHTTPStatusCode code) { return (code / TNLHTTPStatusCodePageSize) == (TNLHTTPStatusCodePageServerError / TNLHTTPStatusCodePageSize); } //! HTTP response is 2xx AND definitely a success (not 202, 203, 207, 208, 226) NS_SWIFT_NAME(getter:TNLHTTPStatusCode.isDefinitiveSuccess(self:)) NS_INLINE BOOL TNLHTTPStatusCodeIsDefinitiveSuccess(TNLHTTPStatusCode statusCode) { if (!TNLHTTPStatusCodeIsSuccess(statusCode)) { return NO; } /// Start: ignore these comments in Swift which are for the relevant ObjC code switch (statusCode) { case TNLHTTPStatusCodeAccepted: // 202 case TNLHTTPStatusCodeNonAuthoritativeInformation: // 203 case TNLHTTPStatusCodeMultiStatus: // 207 case TNLHTTPStatusCodeAlreadyReported: // 208 case TNLHTTPStatusCodeInstanceManipulationUsed: // 226 { return NO; } default: { // All other 2xx HTTP Status Codes are definitive return YES; } } /// End: ignore these comments in Swift which are for the relevant ObjC code } #pragma mark - HTTP Content-Type constants typedef NSString * const TNLHTTPContentType NS_EXTENSIBLE_STRING_ENUM; FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeJPEGImage; // image/jpeg FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeQuicktimeVideo; // video/quicktime FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeJSON; // application/json FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeTextPlain; // text/plain FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeMultipartFormData; // multipart/form-data FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeOctetStream; // application/octet-stream FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeURLEncodedString; // application/x-www-form-urlencoded FOUNDATION_EXTERN TNLHTTPContentType TNLHTTPContentTypeThriftBinary; // application/vnd.apache.thrift.binary //! Is the content type a textual format (limited to UTF8 [default] and ASCII currently), helpful for determining if something is printable or compressable FOUNDATION_EXTERN BOOL TNLHTTPContentTypeIsTextual(NSString * __nullable contentType) NS_SWIFT_NAME(getter:TNLHTTPContentType.isTextual(self:)); #pragma mark - HTTP Dates /** Enum for the different HTTP formats specified by the HTTP specification. From RFC2616 3.3.1 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format Sun Nov 6 08:49:37 +0000 1994 ; ANSI C's asctime() format, extended */ typedef NS_ENUM(NSInteger, TNLHTTPDateFormat) { /** Unknown HTTP date format */ TNLHTTPDateFormatUnknown = 0, /** RFC 822 date format */ TNLHTTPDateFormatRFC822, /** RFC 850 date format */ TNLHTTPDateFormatRFC850, /** ANSI C's date format */ TNLHTTPDateFormatANSIC, /** ANSI C's date format, extended to have timezone support */ TNLHTTPDateFormatANSICExt, /** Automatically choose the format */ TNLHTTPDateFormatAuto = 0, /** RFC 1123 date format which is the same format as RFC 822 */ TNLHTTPDateFormatRFC1123 = TNLHTTPDateFormatRFC822, }; //! Convert an `NSString` to an `NSDate`, optionally decting the format FOUNDATION_EXTERN NSDate * __nullable TNLHTTPDateFromString(NSString * __nullable string, TNLHTTPDateFormat * __nullable detectedFormat) NS_SWIFT_NAME(TNLHTTPDateFormat.convert(string:detectedFormat:)); //! Convert an `NSDate` to an `NSString` in the specified _format_ FOUNDATION_EXTERN NSString * __nullable TNLHTTPDateToString(NSDate * __nullable date, TNLHTTPDateFormat format) NS_SWIFT_NAME(TNLHTTPDateFormat.convert(self:date:)); #if APPLEDOC /** ## TNLHTTPContentType constants TNLHTTPContentType constants are a set of content type constants Use these constants when setting "Content-Type" values or MIME types. - `TNLHTTPContentTypeJPEGImage` - _@"image/jpeg"_ - `TNLHTTPContentTypeQuicktimeVideo` - _@"video/quicktime"_ - `TNLHTTPContentTypeJSON` - _@"application/json"_ - `TNLHTTPContentTypeTextPlain` - _@"text/plain"_ - `TNLHTTPContentTypeMultipartFormData` - _@"multipart/form-data"_ ## TNLHTTPDateFromString NSDate *TNLHTTPDateFromString(NSString *string, TNLHTTPDateFormat *detectedFormat); Convert an `NSString` date to an `NSDate`. Optionally provide a reference to a `TNLHTTPDateFormat` to have the detected date format returned too. ## TNLHTTPDateToString NSString *TNLHTTPDateToString(NSDate *date, TNLHTTPDateFormat format); Convert an `NSDate` to an `NSString` date formatted string. Provide the _format_ desired or `TNLHTTPDateFormatAuto` or `0` to use the default format. */ @interface TNLHTTP @end #endif NS_ASSUME_NONNULL_END