gototen gototen - 9 days ago 5
Objective-C Question

HTTP/2 Server Push in iOS 10

I am trying to get server push working on iOS 10. I am working off of the Akamai HTTP/2 demo.

https://http2.akamai.com/demo

The following is my attempt at testing server push.

@interface ViewController () <NSURLSessionTaskDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

NSString *displayArtUrl;
for(int i=0; i<378; i++) {
displayArtUrl = [NSString stringWithFormat:@"https://http2.akamai.com/demo/tile-%ld.png", (long)i];
NSURL *url = [NSURL URLWithString:displayArtUrl];
NSURLSessionDataTask *downloadTask = [defaultSession
dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
[downloadTask resume];
}

}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {
NSArray *fetchTypes = @[ @"Unknown", @"Network Load", @"Server Push", @"Local Cache" ];

for(NSURLSessionTaskTransactionMetrics *transactionMetrics in [metrics transactionMetrics]) {

NSLog(@"protocol[%@] reuse[%d] fetch:%@ - %@", [transactionMetrics networkProtocolName], [transactionMetrics isReusedConnection], fetchTypes[[transactionMetrics resourceFetchType]], [[transactionMetrics request] URL]);

if([transactionMetrics resourceFetchType] == NSURLSessionTaskMetricsResourceFetchTypeServerPush) {
NSLog(@"Asset was server pushed");
}
}
}

@end


Unfortunately, the logs show that the fetch type is always NSURLSessionTaskMetricsResourceFetchTypeNetworkLoad when I would expect it to be NSURLSessionTaskMetricsResourceFetchTypeServerPush sometimes. The server obviously supports it, as seen in the web demo.

...
2016-11-22 19:27:37.596205 HttpServerPush[2356:735927] protocol[h2] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-4.png
2016-11-22 19:27:37.596960 HttpServerPush[2356:735927] protocol[h2] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-5.png
2016-11-22 19:27:37.597877 HttpServerPush[2356:735927] protocol[h2] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-6.png
2016-11-22 19:27:37.603988 HttpServerPush[2356:735927] protocol[h2] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-1.png
2016-11-22 19:27:37.976911 HttpServerPush[2356:735927] protocol[h2] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-7.png
....


Has anyone had success with HTTP/2 server push on iOS 10? Is there something missing in the way the assets are being requested?

FYI, Charles Proxy seems to get in the way in this scenario. Enabling it causes iOS 10 to stop using HTTP/2 entirely.

...
2016-11-22 19:55:15.763 HttpServerPush[59822:1612935] protocol[http/1.1] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-8.png
2016-11-22 19:55:15.766 HttpServerPush[59822:1612935] protocol[http/1.1] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-11.png
2016-11-22 19:55:15.769 HttpServerPush[59822:1612935] protocol[http/1.1] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-9.png
2016-11-22 19:55:15.771 HttpServerPush[59822:1612935] protocol[http/1.1] reuse[1] fetch:Network Load - https://http2.akamai.com/demo/tile-12.png
...

Answer

As far as I know, the Akamai demo page doesn't currently push any resource. A push occurs when a PUSH_PROMISE frame is sent by the server to the client. nghttp (installable via brew on Mac OS X: brew install nghttp2) can be used to display the frames sent by the server:

$ nghttp -nv 'https://http2.akamai.com/demo' | grep 'PUSH_PROMISE'
$

On the other hand, https://h2o.examp1e.net/, the home page of the H2O HTTP server, does push resources:

$ nghttp -nv 'https://h2o.examp1e.net' | grep 'PUSH_PROMISE'
[  0.587] recv PUSH_PROMISE frame <length=59, flags=0x04, stream_id=13>
[  0.587] recv PUSH_PROMISE frame <length=33, flags=0x04, stream_id=13>
[  0.588] recv PUSH_PROMISE frame <length=35, flags=0x04, stream_id=13>
[  0.588] recv PUSH_PROMISE frame <length=24, flags=0x04, stream_id=13>
[  0.588] recv PUSH_PROMISE frame <length=28, flags=0x04, stream_id=13>
$
Comments