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).