Open openradar-mirror opened 7 years ago
Modified: 2017-09-08T12:03:41.894350
Modified: 2017-09-08T12:03:41.894350
Modified: 2017-09-08T12:03:41.894350
Modified: 2017-09-08T12:03:41.894350
Modified: 2017-09-08T12:03:41.894350
Modified: 2017-09-08T12:03:41.894350
Modified: 2017-09-08T12:03:41.894350
Modified: 2017-09-08T12:03:41.894350
Description
Area: CFNetwork Framework
Summary:
URLProtocol client provided by NSURLSession to the NSURLProtocol instance is not handling cookies in it's -URLProtocol:wasRedirectedToRequest:redirectResponse: -URLProtocol:didReceiveResponse:cacheStoragePolicy: methods when it receives NSHTTPURLResponse instance as a response.
Instead the responsibility of handling cookies is shifted to the NSURLProtocol instance. When CFNetworks HTTP protocol implementation is instantiated with a task originating from the top level session it is able to resolve session's cookie storage properly (via private API) and add cookies to it. But when it is instantiated with task originating from different session (like in case of CustomHTTPProtocol), cookies are being added only to the nested session's cookie storage. And there is no way to work this around and explicitly add cookies to the relevant session's storage as NSURLProtocol instances have no public way to find out which session they are running in, as -[NSURLSessionTask session] property is private.
So if NSURLSession's protocol client was hadnling cookies in
-URLProtocol:wasRedirectedToRequest:redirectResponse: -URLProtocol:didReceiveResponse:cacheStoragePolicy: everything would just work as expected and no work-around would be necessary. And if -[NSURLSessionTask session] was exposed, at least work-around would be possible. But currently there is no way of implementing proper cookie support in custom HTTP protocols.
Steps to Reproduce:
Add CustomHTTPProtocol, CacheStoragePolicy, CanonicalRequest, QNURLSessionDemux from CustomHTTPProcol sample (https://developer.apple.com/library/content/samplecode/CustomHTTPProtocol/Introduction/Intro.html) to your target.
Then add and execute the following code:
import "CustomHTTPProtocol.h"
BOOL isCookiePresent(NSHTTPCookieStorage storage, NSURL url, NSString cookieName) { NSPredicate predicate = [NSPredicate predicateWithBlock:^BOOL(NSHTTPCookie *cookie, id bindings) { return [cookie.name isEqualToString:cookieName]; }]; return [[storage cookiesForURL:url] filteredArrayUsingPredicate:predicate].count != 0; }
void testCookies(NSArray protocolClasses) { NSString cookieName = @"sample_cookie"; NSURL setCookiesURL = [NSURL URLWithString:@"https://httpbin.org/cookies/set?sample_cookie=sample_value"]; NSURL referenceURL = [NSURL URLWithString:@"https://httpbin.org"];
}
int main(int argc, const char * argv[]) { @autoreleasepool { testCookies(nil); NSLog(@"---"); testCookies(@[[CustomHTTPProtocol class]]); } return EXIT_SUCCESS; }
Note: it is not required to be in main(), it may be in a unit test or whatnot…
Expected Results:
Request succeeded: 1 Is cookie present: 1
Request succeeded: 1 Is cookie present: 1
Actual Results:
Request succeeded: 1 Is cookie present: 1
Request succeeded: 1 Is cookie present: 0
Version/Build: Tested on iOS 10.3, iOS 9.3, macOS 10.12 Note: on iOS 11 request fails to complete with CustomHTTPProtocol…
Configuration:
- Product Version: iOS 10.3, iOS 9.3, macOS 10.12 Created: 2017-09-08T11:58:59.054580 Originated: 2017-09-08T00:00:00 Open Radar Link: http://www.openradar.me/34329423