Document version: 2.17.0
Last updated: 08/06/2020
Author: Nolan O'Brien
- Drop support for iOS 8 & 9
- Replace
TNLRequest
class methods with C functions- Swift does not like having an
@interface
have the same name as an@protocol
- It can work, but gets very messy
- Best to avoid it and replace the convenient class method interfaces in Objective-C with C functions
- Though this is a minor version bump, it is API breaking
- There isn't a way to deprecated the old APIs and introduce new ones, we just have to remove the old ones to fix usages in Swift
- Apologies for the inconvenience!
- Swift does not like having an
- Also, update
TNLHTTP.h
to be much more Swift friendly
- Adopt
direct
support for Objective-C code and eliminatePRIVATE_SELF
C function pattern- Preserves Objective-C calling syntax for better code legibility (less C-style calls interleaving ObjC)
- Safer than
PRIVATE_SELF
C functions (don't need to checkself != nil
) - Avoids awkward
self->_ivar
access in the direct methods (can stick with just using_ivar
) - Same low binary overhead as private C functions
- Make
TNLError.h
much more Swift compatible
- Update
TNLCommunicationAgent
to handle reachability behavior changes- The
Network.framwork
can yield an "other" interface when VPN is enabled (on Mac binaries)- Coerce these into WiFi since we don't have a good way to determine the actual interface used at the moment
- The
Network.framework
used to yield WiFi for any network connection on a simulator, but now yields Wired- Rename
TNLNetworkReachabilityReachableViaWiFi
toTNLNetworkReachabilityReachableViaEthernet
and handle both cases as Ethernet
- Rename
- The
- Refactor Service Unavailable Backoff system to be more abstract and support any trigger for backoff
- All
*serviceUnavailableBackoff*
APIs are refactored into*backoff*
APIs - Introduce
[TNLGlobalConfiguration backoffSignaler]
- Implement your own
TNLBackoffSignaler
to customize behavior ... or ... - Default will use
TNLSimpleBackoffSignaler
which will signal on HTTP 503
- Implement your own
- All
- Abstract out Service Unavailable Backoff Behavior for customization to be applied
- See
[TNLGlobalConfiguration serviceUnavailableBackoffBehaviorProvider]
for providing a custom backoff behavior- Implement your own
TNLServiceUnavailableBackoffBehaviorProvider
to customize behavior - Due to Service Unavailable signaling being opaque, only the HTTP Headers and the URL can be provided
- Implement your own
- Default will use
TNLSimpleServiceUnavailableBackoffBehaviorProvider
- Exact same behavior as before (introduced in TNL prior to v2.0 open sourcing)
- See
- Change the
TNLURLSessionAuthChallengeCompletionBlock
arguments- Leave the disposition parameter
- Change the credentials parameter of
NSURLCredentials
to be credentialsOrCancelContext ofid
- This will permit
TNLAuthenticationChallengeHandler
instance to be able to cancel the challenge and provide extra context in the resulting error code - Twitter will use this to cancel 401 login auth challenges when we don't want a redundant request to be made (since it just yields the same response)
- This is to facilitate working around the behavior in
NSURLSession
where an HTTP 401 response withWWW-Authenticate
header will always be transparently be retried (even when unmodified yielding the identical 401 response). - An additionaly problem is that canceling the 401 response will discard the response's body. If there is information needed in the response body, it will be lost.
- Twitter has updated its
WWW-Authenticate
header responses to include additional metadata since the response body cannot be used. - Apple Feedback:
FB7697492
- This is to facilitate working around the behavior in
- This will permit
- Add retriable dependencies to
TNLRequestOperation
- Whenever a
TNLRetryPolicyProvider
would yield a retry, that retry will be delayed by the longer of 2 things:- The delay provided by the retry policy provider (minimum of 100 milliseconds)
- Waiting for all
dependencies
on theTNLRequestOperation
to complete
- Normally, all
dependencies
of a retryingTNLRequestOperation
will be complete before it has started but it is now possible to add dependencies after the request operation has already started to increase the dependencies on a retry starting.
- Whenever a
- Introduce
tnlcli
, a command-line-interface for TNL- Like cURL but with TNL features
- Verbose mode provides all TNL logging to stdout / stderr along with lots of other details
- Add expensive and constrained conditions to the reachability flags on iOS 13+
TNLNetworkReachabilityMaskPathConditionExpensive
for when path is expensiveTNLNetworkReachabilityMaskPathConditionConstrained
for when path is constrained
- Disable
connectivityOptions
onTNLRequestConfiguration
for iOS 13.0 (ok on iOS 13.1+)connectivityOptions
are backed byNSURLSessionConfiguration
waitsForConnectivity
waitsForConnectivity
regressed in iOS 13 betas and is unuseable as a feature on iOS 13.0.- iOS 13.1 beta 1 addressed this issue.
- Expose
shouldUseExtendedBackgroundIdleMode
inTNLRequestConfiguration
- There's a lot of nuance to this configuration property, so take care when using it
- Change it so that iOS 12 and above use Network.framework for reachability instead of SystemConfiguration.framework
- Reachability in SystemConfiguration.framework has been broken in simulator since iOS 11
- Reachability in SystemConfiguration.framework will no longer work at all starting in iOS 13
- Reachability using
nw_path_monitor_t
is the new canonical way to observe reachability changes, so we'll use that
- Change network reachability flags in
TNLCommunicationAgent
fromSCNetworkReachabilityFlags
toTNLNetworkReachabilityFlags
- On iOS 11 and below, the flags are exactly the same as
SCNetworkReachabilityFlags
- On iOS 12 and above, the flags now map to the new
TNLNetworkReachabilityMask
flags
- On iOS 11 and below, the flags are exactly the same as
- Change
TNLRequestConfiguration
to accept aTNLResponseHashComputeAlgorithm
to specify how to hash- MD5 was marked deprecated in iOS 13, so providing a wider range of algorithms without eliminating MD5 support is needed
- Fix terrible bug where cancelling all request operations for any
TNLRequestOperationQueue
will cancel all request operations for all queues!
- Move away from mach time for metrics to
NSDate
instances- This better mirrors what Apple does
- Avoids the pitfall of using mach times as more than just measurements of durations and using them as reference timestamps (which is frought)
- Using
NSDate
now does have the problem of clock changes impacting timings, but this is so infrequent it practically won't ever affect metrics from TNL
- Add
sessionId
toTNLAttemptMetaData
- Helps keep track of what
NSURLSession
was used
- Helps keep track of what
- Add
taskResumePriority
toTNLAttemptMetaData
- Helps keep track of what QOS was used when
resume
was called for the underlyingNSURLSessionTask
- Helps keep track of what QOS was used when
- Add
taskResumeLatency
toTNLAttemptMetaData
- Helps diagnose if there is some unforseen stall between calling
resume
for the task and the fetching actuallying starting
- Helps diagnose if there is some unforseen stall between calling
- Add
taskMetricsAfterCompletionLatency
andtaskWithoutMetricsCompletionLatency
toTNLAttemptMetaData
- Helps track when radar
#27098270
occurs
- Helps track when radar
- Add
[TNLGlobalConfiguration URLSessionPruneOptions]
- These options offer ways for TNL to prune inactive internal
NSURLSession
instances more aggressively than the 12 session limit does - Options can be a combination of: on memory warning, on app background and/or after every network task
- Callers can also provide a special option to prune now
- These options offer ways for TNL to prune inactive internal
- Add
[TNLGlobalConfiguration URLSessionInactivityThreshold]
- Works with
URLSessionPruneOptions
by limiting whatNSURLSession
intances are inactive by requiring a duration to elapse since the last network task ran
- Works with
- Add
[TNLGlobalConfiguration pruneURLSessionMatchingRequestConfiguration:operationQueueId:]
- Offers a way to explicitely purge a specific underlying
NSURLSession
based on a givenTNLRequestConfiguration
and aTNLRequestOperationQueue
instance'sidentifier
- Offers a way to explicitely purge a specific underlying
Author: Laurentiu Dascalu
- Expose method on
TNLLogger
to redact desired header fields from being logged - Good for redacting things you don't want to log like
Authorization
header field
- Add captive portal detection to
TNLCommunicationAgent
- detects when a known HTTP (non-HTTPS) endpoint is intercepted via a captive portal
- this mechanism is a solid tradeoff in coverage vs complexity
- there are many ways captive portals can manifest beyond what TNL detects
- a 100% coverage is extremely complicated and 100% accuracy is not feasible
- supporting the simplest mechanism for detection is sufficient for most detection use cases
- Add background upload support using
HTTPBody
- TNL will encapsulate the busy-work if there is an upload desire via an
HTTPBody
instead of anHTTPFilePath
- TNL will encapsulate the busy-work if there is an upload desire via an
- Other miscellaneous minor fixes
- drop iOS 7 support
- removes some compatibility check APIs that are no longer necessary too
- revise
TNLRetryPolicyProvider
interface to optionally provide a newTNLRequestConfiguration
when retrying- prior interface only permitted updating the idleTimeout which was not sufficient for more use cases
- example use case: provide a custom content encoder that fails to encode a request, the retry policy and update the configuration to remove the custom content encoder to try again without encoding
- add demuxing support for
URLCache
,URLCredentialStorage
, andcookieStorage
onTNLRequestConfiguration
- reduces the number of
NSURLSession
instances that need to be spun up
- reduces the number of
- add
waitsForConnectivity
support viaconnectivityOptions
forTNLRequestConfiguration
- Open source TNL!!!
- Make TNL protocols adopt
tnl_
method prefixes
- Add support to have
TNLRequestOperation
instances' underlying network operations have dependencies set as the network operation(s) enqueue. - See
requestOperation:readyToEnqueueUnderlyingNetworkingOperation:
- Clean up retry policy provider code and event callbacks for disambiguity, and reduced coupling.
- Improve auth challenge support
- Create
TNLAuthenticationChallengeHandler
- Add registration/unregistration on global config for auth challenge handler(s)
- Remove
TNLTLSTrustEvaluator
protocol and property from global config - Remove auth challenge callback to
TNLRequestAuthorizer
(part ofTNLRequestDelegate
) - Auth challenges are a shared concept and not associated with any given request specifically
- Handling challenges on a per request basis made for complex code and cascading handling that was unnecessary
- A concrete implementation of a
TNLAuthenticationChallengeHandler
can behave just like a TLS trust evaluator or any number of auth challenge behaviors now.
- Elevate
NSNumber
to be a first class object withinTNLParameterCollection
- Default will encode as a number always.
- URL encoder option to encode Boolean
NSNumber
objects astrue
orfalse
instead of1
and0
- Persists the
NSNumber
when creating an encodable dictionary from aTNLParameterCollection
instead of converting to a string - This helps with JSON serialization which will want the NSNumber serialized as a number or boolean, instead of a string
- Twitter Network Layer has been stable without revision for 12 months!
- 15 months if you exclude the removal of
CocoaSPDY
which was just removing a plugin feature.
- Remove CocoaSPDY support
- Add auth hydration step to
TNLRequestAuthorizer
- this helps decouple things so consumers can hydrate the request in one step and authorize in another
- since TNL has host sanitization, it is often necessary to authorize a request with whatever the sanitized host is. This decoupling enables that flow very simply.
- Add
TNLCommunicationAgent
for communication trait support in TNL - monitors reachability, carrier info and WWAN radio access tech
- Add support for custom encoders and decoders for additional
Content-Encoding
types - Useful for supporting compressed uploads
- Useful for using different compression codecs on responses that could have higher compression ratios than
gzip
- Add
[TNLGlobalConfiguration operationAutomaticDependencyPriorityThreshold]
to support having higher priority requests preventing lower priority requests from running - The value of this feature is to gate all other network interference when a critical request that much be executed as fast as possible is being run
- This feature takes advantage of the
NSOperation
dependency support
- Revise
TNLPseudoURLProtocol
to take aTNLPseudoURLResponseConfig
- Offers easier control over the canned responses behavior
- Does change the pattern from the request owning the behavior via headers to the response owning behavior when registered (with a config)
- this is an improvement since it moves the ownership so that the user of
TNLPseudoURLProtocol
doesn't need to control the request being sent
- Add
NSURLSessionTaskMetrics
support for iOS 10 and macOS 10.12 - Just tacked onto
TNLAttemptMetrics
for now
- Remove long standing workaround in TNL to get the
NSURLResponse
of anNSURLSessionTask
via KVO instead of the delegate callback due to significant problems on iOS 8 & Mac OS X 10.10
Author: Zhen Ma
- Do not call didCompleteAttempt with TNLAttemptCompleteDispositionCompleting when the state is TNLRequestOperationStateWaitingToRetry.
Author: Feng Yun
- Allow multiple global header providers to apply to all requests.
- Expose
TNLTiming.h
for timing helper functions - Fix bug failing to detect Auth Challenge Cancellations
- Add support for global configurable
TNLTLSTrustEvaluator
- This is placeholder while CocoaSPDY continutes to use a trust evaluator instead of
NSURLAuthenticationChallenge
pattern
- Have
[TNLGlobalConfiguration requestOperationCallbackTimeout]
be used to enabled/disable callback clog detection too. Set it to0.0
or negative to disable the detection - Added a bug fix around clog detection when app becomes inactive too
- Remove Twitter specific logging framework dependency and expose hooks to provide any desired logger. CocoaSPDY support has its own logger and doesn't share the TwitterNetworkLayer logger.
- Split callback clogging timeout from idle timeout
TNLRequestOperation
instances can clog with the callback timeout, configured onTNLGlobalConfiguration
- Callback timeout will pause while an iOS app is in the background
- remove
requiresStrongReference
fromTNLRequestDelegate
- The responsibility of the delegate's lifecycle belongs to the owner of the delegate, not to the delegate itself
- Simplest way to adapt is to make the delegate be the
context
of the operation
- Add
TNLAttemptCompleteDisposition
to our attempt completion callbacks in TNL. This will aid in identifying if the attempt will yield additional work (Retry or Redirect) or not (Complete)
- iOS 9 has disabled support for subclassing empty
NSURLCache
(they now check the size ivars withouth accessing the property methods). As such, we need to update our "cache hit detection" code so that it doesn't use a customNSURLCache
subclass. - This means our observing of responses is now more fragile in detecting cache hits.
NSCachedURLResponse(TNLCacheAddtions)
andNSURLResponse(TNLCacheAddtions)
are now exposed so that if cache hit detection is desired w/ anNSURLCache
that is shared between TNL and some other networking code it can be achieved, though admittedly with burden.- If networking is isolated to TNL, there won't be an issue.
- Increase NSURLSession reuse by improving the session identifier used for non-background URL sessions.
- Split out NSURLSession work from TNLRequestOperationQueue into a TNLURLSessionManager object. This will prepare room for betture NSURLSession reuse and modularity in TNL.
- Rename TNLConnectionOperation to TNLURLSessionTaskOperation. This improves naming cohesion for the operation and leaves room for us to add a TNLURLConnectionOperation which would wrap NSURLConnection if we choose to add that support.
- Persist NSURLSession instances to maximize reuse
Author: John Zhang
- Added optional idleTimeoutOfRetryForRequestOperation:withResponse: to TNLRequestRetryPolicyProvider protocol
- Handled the return value of idleTimeoutOfRetryForRequestOperation:withResponse: in TNLRequestOperation
- Make TNLParameterCollection throw exception on zero length keys
- Treat zero length keys in TNLDecodeDictionary and TNLEncodeDictionary as invalid and discard the key-value-pair when encountered
- Make CocoaSPDY optional
- Add default TNLURLEncodableObject support to NSNumber
- Add valueForResponseHeaderField: to TNLResponseInfo
- Collapse TNLHTTPAttempMetaData and TNLSPDYAttemptMetaData into their superclass TNLAttemptMetaData.
- Default
TNLRequestConfiguration
to havenil
forURLCache
,URLCredentialStore
andcookieStore
- Add
TNLRequestConfiguration
constructor for different request anatomies (request vs response sizes)
- Change
requestOperation:didCompleteAttemptWithInfo:metrics:error:
torequestOperation:didCompleteAttemptWithIntermediateResponse:disposition:
- This alleviates bugs with dealing with responseClass hydration when observing an attempt
- Remove
TNLResponseHydrater
- Add
Class
argument toTNLRequestOperation
constructors so that we can provide the responseClass
- Refactor
TNLResponseHydrater
to provide aClass
that is ingested by theTNLRequestOperation
at init time. - This alleviates a complex surface area that was exposed where the
TNLRequestOperation
is in theBuildingResponse
state. - Results in
BuildingResponse
value being removed fromTNLRequestOperationState
.
Author: John Zhang
- Updated TNLHTTPHeaderProvider to pass in a id parameter for context
- Add nullable/nonnull keywords for Swift interop and compiler optimizations
- Permit HTTP Status Codes 202, 203, 207, 208, and 226 to be retriable with a retry policy provider
- Add TNLURLEncodableDictionary to TNLURLCoding
- Add encodableDictionaryValueWithOptions: to TNLParameterCollection
- Make default behavior for TNLURLEncodeDictionary to throw an exception when an unsupported value is encountered
- TNLParameterCollection will now remove the value when
nil
is set as the value
Author: Kevin Goodier
- Added additional CocoaSPDY fields to TNLSPDYAttemptMetadata for stream timings
- Removed support externally for metadata dictionary
- Added
TNLHTTPHeaderProvider
support
- Provide operation to delegate callbacks that retrieve the background and completion queues
Author: John Zhang
- Added operationId to TNLRequestOperation
- Added attemptId and startTime to TNLAttemptMetrics
- Changed request:didStartAttemptRequest:withType to requestOperation:request:didStartAttemptRequest:metrics in TNLNetworkObserver
- Changed request:didCompleteAttemptWithInfo:metrics:error to requestOperation:didCompleteAttemptWithInfo:metrics:error in TNLNetworkObserver
- Update docs
- Change TNLNetwork functions to be class methods on a
TNLNetwork
static class - Rename
TNLNetworkGlobalExecutingNetworkConnections*
definitions to beTNLNetworkExecutingNetworkConnections*
- Rename
TNLHTTPRequest
protocol toTNLRequest
- This will help disambiguate from the
TNLHTTPRequest
object - Make
URL
a required method onTNLRequest
- Change NSObject pattern to id
- Add more documentation around
TNLRequest
s and hydration
- Ensure that the completion callback on the
TNLRequestDelegate
or the completion block is called before theTNLRequestOperation
finishes - This will permit
waitUntilFinished
andwaitUntilFinishedWithoutBlockingRunLoop
to return after the callback has completed
- Increase compatibility with a more diverse set of requests.
- Permit any request
HTTPMethod
to be an upload, provided it has a body. - Permit any request
HTTPMethod
to be a download, provided the response data consumption mode isTNLResponseDataConsumptionModeSaveToDisk
- There are exceptions that can result in errors based on NSURL framework's restrictions
- Add
[TNLAttemptMetrics URLResponse]
and[TNLAttemptMetrics operationError]
- This provides a nice trail of breadcrumbs for inspecting the details of how an operation executed
- Add support for configuring cookies in
TNLRequestConfiguration
- Cookies were off by default, now they follow
NSURLSessionConfiguration
defaults
- Add
TNLRedirectPolicyUseCallback
to redirect policies - This exposes additional control to the
TNLRequestRedirecter
protocol (on theTNLRequestDelegate
) while keeping the simpler configs available
- Redefine
TNLNetworkObserver
for much greater utility - Have the
TNLGlobalConfiguration
support multiple network observers instead of just one
- Add
TNLAttemptMetrics
class andTNLAttemptMetaData
classes for concrete access to metrics and meta-data
- Remove
state
property ofTNLRequestOperationQueue
. It is unused and the backing logic is expensive. If this functionality is needed in the future we can add it in a more efficient way.
- Add support for making in app request operations be background tasks with
TNLRequestExecutionModeInAppBackgroundTask
. See[TNLRequestConfiguration executionMode]
.
- Add redirect tracking in
TNLResponseMetrics
- Rework
TNLResponseMetrics
to support[TNLResponseMetrics attemptMetrics]
built ofTNLResponseAttemptMetrics
- Add an optional method to
TNLRequestDelegate
to provide thecompletionQueue
which will default todispatch_get_main_queue()
. This will maintain the optimization of defaulting delegate callbacks to a backgroung queue while adding the safety of completing the execution on the main queue to avoid potential gotchas on completion.
- Change
[TNLResponse error]
to[TNLResponse operationError]
- Add
TNLResponseHydrater
protocol for optional response hydration
- Greatly improve robustness of
TNLParameterCollection
- Add encoding configurability with
TNLURLEncodingOptions
- Add decoding configurability with
TNLURLDecodingOptions
- Add dynamic support for encoding objects with the
TNLURLEncodableObject
protocol. - Add
TNLURLEncodeDictionary
function - Deprecate
TNLURLGenerateParameterString
function - Add
TNLURLDecodeDictionary
function - Deprecate
TNLURLGenerateParameterDictionary
function
- Add
[TNLRequestEventHandler requestOperation:didReceiveURLResponse:]
delegate callback
- Add proxy objects for
[NSURLCache tnl_shareURLCache]
and[NSURLCredentialStorage tnl_shareCredentialStorage]
- Make proxy objects defaults of
TNLRequestConfiguration
- Add convenience "Retry-After" header support to
TNLResponseInfo
- Change default
TNLRequestRedirectPolicy
to beTNLRequestRedirectPolicyDoRedirect
- Completely encapsulate CocoaSPDY
TNLGlobalConfiguration(CocoaSPDYAdditions)
[TNLRequestConfiguration protocolOptions]
TNLCocoaSPDYConfiguration
[TNLResponseMetrics cocoaSPDYMetaData]
TNLCocoaSPDY.h
- Remove
NSCopying
requirement fromTNLHTTPRequest
protocol - Add
NSCopying
support toTNLParameterCollection
- Rework delegate pattern for
TNLRequestOperation
. #simplify
- Add support for URL host sanitization
- Prevent
[TNLRequestOperationQueue defaultOperationQueue]
from being suspended
- Initial release
- Inaugural beta