Blog What we do Support Community
Login Sign up

HTTP/2 Server Push with multiple assets per Link header

by John Graham-Cumming.

In April we announced that we had added experimental support for HTTP/2 Server Push to all CloudFlare web sites. We did this so that our customers could iterate on this new functionality.


CC BY 2.0 image by https://www.flickr.com/photos/mryipyop/

Our implementation of Server Push made use of the HTTP Link header as detailed in W3C Preload Working Draft.

We also showed how to make Server Push work from within PHP code and many people started testing and using this feature.

However, there was a serious restriction in our initial version: it was not possible to specify more than one asset per Link header for Server Push and many CMS and web development platforms would not allow multiple Link headers.

We have now addressed that problem and it is possible to request that multiple assets be pushed in a single Link header. This change is live and was used to push assets in this blog post to your browser if your browser supports HTTP/2.

When CloudFlare reads a Link header sent by an origin web server it will remove assets that it pushes from the Link header passed on to the web browser. That made it a little difficult to debug problems with Link and Server Push so we have added a header called Cf-H2-Pushed which contains the assets that were pushed.

For example, browsing to this recent blog post results in the origin web server sending the following headers:

Cache-Control: public, max-age=0
Content-Encoding: gzip
Content-Length: 33640
Content-Type: text/html; charset=utf-8
Date: Wed, 29 Jun 2016 16:09:37 GMT
Expires: Wed, 29 Jun 2016 16:10:07 GMT
Link: </assets/css/screen.css?v=5fc240c512>; rel=preload; as=style,<//cdn.bizible.com/scripts/bizible.js>; rel=preload; as=script,</content/images/2016/06/Timeouts-001.png>; rel=preload; as=image,</content/images/2016/06/Timeouts-002.png>; rel=preload; as=image,<//platform.linkedin.com/in.js>; rel=preload; as=script,<https://code.jquery.com/jquery-1.11.3.min.js>; rel=preload; as=script,</assets/js/jquery.fitvids.js?v=5fc240c512>; rel=preload; as=script
Vary: Accept-Encoding
X-Ghost-Cache-Status:From Cache
X-Powered-By: Express 

CloudFlare decides to HTTP/2 Server Push the assets /assets/css/screen.css?v=5fc240c512, /content/images/2016/06/Timeouts-001.png, /content/images/2016/06/Timeouts-002.png and /assets/js/jquery.fitvids.js?v=5fc240c512. As the response passes through CloudFlare those assets are removed from the Link header, pushed and added to the Cf-H2-Pushed header:

cache-control:public, max-age=30
cf-cache-status:EXPIRED
cf-h2-pushed:</assets/css/screen.css?v=5fc240c512>,</content/images/2016/06/Timeouts-001.png>,</content/images/2016/06/Timeouts-002.png>,</assets/js/jquery.fitvids.js?v=5fc240c512>
content-encoding:gzip
content-type:text/html; charset=utf-8
date:Wed, 29 Jun 2016 16:09:37 GMT
expires:Wed, 29 Jun 2016 16:10:07 GMT
link:<//cdn.bizible.com/scripts/bizible.js>; rel=preload; as=script,<//platform.linkedin.com/in.js>; rel=preload; as=script,<https://code.jquery.com/jquery-1.11.3.min.js>; rel=preload; as=script
server:cloudflare-nginx
status:200 OK
vary:Accept-Encoding
x-ghost-cache-status:From Cache
x-powered-by:Express

In Google Chrome Canary's Developer view the pushed assets can be clearly seen.

Conclusion

Please let us know how you use Server Push. We're particularly interested in experiences with pushing different types of resources (images vs. styles vs. scripts) and working out the optimal number of items to push (we currently allow up to 50 resources per page).

comments powered by Disqus