
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Mon, 13 Apr 2026 18:04:06 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Accelerating Node.js applications with HTTP/2 Server Push]]></title>
            <link>https://blog.cloudflare.com/accelerating-node-js-applications-with-http-2-server-push/</link>
            <pubDate>Tue, 16 Aug 2016 12:17:19 GMT</pubDate>
            <description><![CDATA[ In April, we announced support for HTTP/2 Server Push via the HTTP Link header. My coworker John has demonstrated how easy it is to add Server Push to an example PHP application.  We wanted to make it easy to improve the performance of contemporary websites built with Node.js.  ]]></description>
            <content:encoded><![CDATA[ <p>In April, we announced support for <a href="https://www.cloudflare.com/http2/server-push/">HTTP/2 Server Push</a> via the HTTP <code>Link</code> header. My coworker John has demonstrated how easy it is to <a href="/using-http-2-server-push-with-php/">add Server Push to an example PHP</a> application.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2cTvkkBKYrTnHNyFrfyrYI/05d92efb1903cd4700d8a9020e430b40/489477622_594bf9e3d9_z.jpg" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a> <a href="https://www.flickr.com/photos/nickyfern/489477622/in/photolist-KfGDm-4WuA7B-4WySRS-a8ijnt-4WuByk-4WuB9M-bE3e6V-665C6K-eeQRx1-b97viM-qzYJ8z-9n2aTS-8EsaQK-aqxV42-jWDkD2-jKyWKv-jzs7yy-9TKcYn-4iAQTa-ECjYJ-96MvXy-bP43v2-rEmKWR-5p3k5r-pVZhDo-os1Njy-5CEEnU-8RhgUX-7JV4jr-9bC7me-sSKqA-72Mppz-maZfyL-6KfUge-dDvw4S-ngyFgY-aPxqsP-7b24QV-5opdXV-sEA7Xj-mZohS-8GFkMr-twfh93-7ZXqtJ-dvRbXj-a8mRiU-4NCzeD-qFXKpj-4n7K7j-34D66Q">image</a> by <a href="https://www.flickr.com/photos/nickyfern/">Nicky Fernandes</a></p><p>We wanted to make it easy to improve the performance of contemporary websites built with <a href="https://nodejs.org/">Node.js</a>. we developed the <a href="https://github.com/cloudflare/netjet">netjet</a> middleware to parse the generated HTML and automatically add the <code>Link</code> headers. When used with an example Express application you can see the headers being added:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4yzfZDbCTajZyJDNnbqrUm/ab28553b5d5e878e10b93f115a0f602e/2016-08-11_13-32-45.png" />
            
            </figure><p>We use <a href="https://ghost.org/">Ghost</a> to power this blog, so if your browser supports HTTP/2 you have already benefited from Server Push without realizing it! More on that below.</p><p>In netjet, we use the <a href="https://github.com/posthtml/posthtml">PostHTML</a> project to parse the HTML with a custom plugin. Right now it is looking for images, scripts and external stylesheets. You can implement this same technique in other environments too.</p><p>Putting an HTML parser in the response stack has a downside: it will increase the page load latency (or "time to first byte"). In most cases, the added latency will be overshadowed by other parts of your application, such as database access. However, netjet includes an adjustable LRU cache keyed by <code>ETag</code> headers, allowing netjet to insert <code>Link</code> headers quickly on pages already parsed.</p><p>If you are designing a brand new application, however, you should consider storing metadata on embedded resources alongside your content, eliminating the HTML parse, and possible latency increase, entirely.</p><p>Netjet is compatible with any Node.js HTML framework that supports Express-like middleware. Getting started is as simple as adding netjet to the beginning of your middleware chain.</p>
            <pre><code>var express = require('express');
var netjet = require('netjet');
var root = '/path/to/static/folder';

express()
  .use(netjet({
    cache: {
      max: 100
    }
  }))
  .use(express.static(root))
  .listen(1337);</code></pre>
            <p>With a little more work, you can even use netjet without frameworks.</p>
            <pre><code>var http = require('http');
var netjet = require('netjet');

var port = 1337;
var hostname = 'localhost';
var preload = netjet({
  cache: {
    max: 100
  }
});

var server = http.createServer(function (req, res) {
  preload(req, res, function () {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/html');
      res.end('&lt;!doctype html&gt;&lt;h1&gt;Hello World&lt;/h1&gt;');
  });
});

server.listen(port, hostname, function () {
  console.log('Server running at http://' + hostname + ':' + port+ '/');
});</code></pre>
            <p>See the <a href="https://www.npmjs.com/package/netjet">netjet documentation</a> for more information on the supported options.</p>
    <div>
      <h2>Seeing what’s pushed</h2>
      <a href="#seeing-whats-pushed">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2qCaQEt8gl74hBdoZVEzBS/d29a6028893b87b888cad5ba438b3a78/2016-08-02_10-49-33.png" />
            
            </figure><p>Chrome's Developer Tools makes it easy to verify that your site is using Server Push. The Network tab shows pushed assets with "Push" included as part of the initiator.</p><p>Unfortunately, Firefox's Developers Tools don't yet directly expose if the resource pushed. You can, however, check for the <code>cf-h2-pushed</code> header in the page's response headers, which contains a list of resources that CloudFlare offered browsers over Server Push.</p><p>Contributions to improve netjet or the documentation are greatly appreciated. I'm excited to hear where people are using netjet.</p>
    <div>
      <h2>Ghost and Server Push</h2>
      <a href="#ghost-and-server-push">
        
      </a>
    </div>
    <p>Ghost is one such exciting integration. With the aid of the Ghost team, I've integrated netjet, and it has been available as an opt-in beta since version 0.8.0.</p><p>If you are running a Ghost instance, you can enable Server Push by modifying the server's <code>config.js</code> file and add the <code>preloadHeaders</code> option to the <code>production</code> configuration block.</p>
            <pre><code>production: { 
  url: 'https://my-ghost-blog.com', 
  preloadHeaders: 100, 
  // ... 
}</code></pre>
            <p>Ghost has put together <a href="http://support.ghost.org/preload-headers/">a support article</a> for Ghost(Pro) customers.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>With netjet, your Node.js applications can start to use browser preloading and, when used with CloudFlare, HTTP/2 Server Push today.</p><p>At CloudFlare, we're excited to make tools to help increase the performance of websites. If you find this interesting, we are <a href="https://www.cloudflare.com/join-our-team/">hiring</a> in Austin, Texas; Champaign, Illinois; London; San Francisco; and Singapore.</p> ]]></content:encoded>
            <category><![CDATA[HTTP2]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[Server Push]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[JavaScript]]></category>
            <guid isPermaLink="false">257O1UR4TetOqSjjwVfDCV</guid>
            <dc:creator>Terin Stock</dc:creator>
        </item>
        <item>
            <title><![CDATA[Ask Some HTTP/2 Pros The Hard Questions]]></title>
            <link>https://blog.cloudflare.com/ask-some-http-2-pros-the-hard-questions/</link>
            <pubDate>Wed, 20 Jul 2016 00:27:17 GMT</pubDate>
            <description><![CDATA[ We're big fans of HTTP/2 and our customers make up the majority of HTTP/2 enabled domains today. HTTP/2 is a key part of the modern web, and its growth and adoption is changing how websites and applications are built. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We're big fans of HTTP/2 and <a href="/cloudflares-impact-on-the-http-2-universe/">our customers make up the majority of HTTP/2 enabled domains today</a>. HTTP/2 is a key part of the modern web, and its growth and adoption is changing how websites and applications are built.</p><p>On Thursday July 21, 2016, join web performance experts Ilya Grigorik (Web Performance Engineer at Google) and Suzanne Aldrich (Solutions Engineer at CloudFlare), as they discuss the latest in HTTP/2 and Server Push, the tools and resources you can use today to build fast and scalable web apps, and ways to speed up your content on any device.</p><p><b>When</b>: Thursday July 21, 2016 from 1pm-2pm Eastern Time (1500 – 1600 UTC)</p><p><b>Who</b>: CloudFlare’s own <a href="https://twitter.com/SuzanneAldrich">Suzanne Aldrich</a> and <a href="https://twitter.com/igrigorik">Ilya Grigorik</a> from Google</p><p>Need the basics of HTTP/2 and Server Push? Visit the <a href="https://www.cloudflare.com/http2/">CloudFlare HTTP/2 website</a>.</p> ]]></content:encoded>
            <category><![CDATA[HTTP2]]></category>
            <category><![CDATA[Webinars]]></category>
            <category><![CDATA[Events]]></category>
            <category><![CDATA[Server Push]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">qhT0yOb5VMVYQD7sySd5Z</guid>
            <dc:creator>Elenitsa Staykova</dc:creator>
        </item>
        <item>
            <title><![CDATA[HTTP/2 Server Push with multiple assets per Link header]]></title>
            <link>https://blog.cloudflare.com/http-2-server-push-with-multiple-assets-per-link-header/</link>
            <pubDate>Thu, 30 Jun 2016 12:09:46 GMT</pubDate>
            <description><![CDATA[ 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.

 ]]></description>
            <content:encoded><![CDATA[ <p>In April we <a href="/announcing-support-for-http-2-server-push-2/">announced</a> that we had added experimental support for <a href="https://www.cloudflare.com/http2/server-push/">HTTP/2 Server Push</a> to all CloudFlare web sites. We did this so that our customers could iterate on this new functionality.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1Sxm8MH00rIckiWtjvxz71/9f4c2227696b67a4e19db037e18bb80d/1673801831_a93ecfc3c4_z.jpg" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a> <a href="https://www.flickr.com/photos/mryipyop/1673801831/in/photolist-3xUEYg-nMS6rx-jvSsLx-9oBV3s-8KH2YK-o54g8R-8h4bmw-eapSfS-cj4No3-nMSXLP-nMRZQJ-iNpH9k-hcr3m3-nMS6ui-5RDVrK-fAaYES-nMXwba-cNFT3N-iZDTWg-k5VzKt-jeJE8T-7bM32E-d3rznG-89jZ9e-aVLkBT-4y2kdD-qtKzjY-62Yv2h-5WcKeC-87jJdA-5Es3vn-bQ8W5a-7DhbKd-hE5oza-6NutL7-5WLwFt-hcnrny-5WAoU1-5mSoVV-8RSQ7A-gXiVcG-5Wp6pS-8GFkMr-hcoeN9-bC1zH5-ePG8BQ-hcokfv-hcpgme-hcqQ59-qUkfTa">image</a> by <a href="Mike">https://www.flickr.com/photos/mryipyop/</a></p><p>Our implementation of Server Push made use of the <a href="/announcing-support-for-http-2-server-push-2/#fnref:1">HTTP <code>Link</code></a> header as detailed in W3C <a href="https://www.w3.org/TR/preload/">Preload</a> Working Draft.</p><p>We also showed how to make Server Push work from within <a href="/using-http-2-server-push-with-php/">PHP code</a> and many people started testing and using this feature.</p><p>However, there was a serious restriction in our initial version: it was not possible to specify more than one asset per <code>Link</code> header for Server Push and many CMS and web development platforms would not allow multiple <code>Link</code> headers.</p><p>We have now addressed that problem and it is possible to request that multiple assets be pushed in a single <code>Link</code> header. This change is live and was used to push assets in this blog post to your browser if your browser supports HTTP/2.</p><p>When CloudFlare reads a <code>Link</code> header sent by an origin web server it will remove assets that it pushes from the <code>Link</code> header passed on to the web browser. That made it a little difficult to debug problems with <code>Link</code> and Server Push so we have added a header called <code>Cf-H2-Pushed</code> which contains the assets that were pushed.</p><p>For example, browsing to this <a href="/the-complete-guide-to-golang-net-http-timeouts/">recent</a> blog post results in the origin web server sending the following headers:</p>
            <pre><code>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: &lt;/assets/css/screen.css?v=5fc240c512&gt;; rel=preload; as=style,&lt;//cdn.bizible.com/scripts/bizible.js&gt;; rel=preload; as=script,&lt;/content/images/2016/06/Timeouts-001.png&gt;; rel=preload; as=image,&lt;/content/images/2016/06/Timeouts-002.png&gt;; rel=preload; as=image,&lt;//platform.linkedin.com/in.js&gt;; rel=preload; as=script,&lt;https://code.jquery.com/jquery-1.11.3.min.js&gt;; rel=preload; as=script,&lt;/assets/js/jquery.fitvids.js?v=5fc240c512&gt;; rel=preload; as=script
Vary: Accept-Encoding
X-Ghost-Cache-Status:From Cache
X-Powered-By: Express </code></pre>
            <p>CloudFlare decides to HTTP/2 Server Push the assets <code>/assets/css/screen.css?v=5fc240c512</code>, <code>/content/images/2016/06/Timeouts-001.png</code>, <code>/content/images/2016/06/Timeouts-002.png</code> and <code>/assets/js/jquery.fitvids.js?v=5fc240c512</code>. As the response passes through CloudFlare those assets are removed from the <code>Link</code> header, pushed and added to the <code>Cf-H2-Pushed</code> header:</p>
            <pre><code>cache-control:public, max-age=30
cf-cache-status:EXPIRED
cf-h2-pushed:&lt;/assets/css/screen.css?v=5fc240c512&gt;,&lt;/content/images/2016/06/Timeouts-001.png&gt;,&lt;/content/images/2016/06/Timeouts-002.png&gt;,&lt;/assets/js/jquery.fitvids.js?v=5fc240c512&gt;
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:&lt;//cdn.bizible.com/scripts/bizible.js&gt;; rel=preload; as=script,&lt;//platform.linkedin.com/in.js&gt;; rel=preload; as=script,&lt;https://code.jquery.com/jquery-1.11.3.min.js&gt;; rel=preload; as=script
server:cloudflare-nginx
status:200 OK
vary:Accept-Encoding
x-ghost-cache-status:From Cache
x-powered-by:Express</code></pre>
            <p>In Google Chrome Canary's Developer view the pushed assets can be clearly seen.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2jgGCv0Nr84rpBYTGKMQ5l/b27d125a7a1e3f827e15118c213e4666/Screen-Shot-2016-06-30-at-11-15-02.png" />
            
            </figure>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>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).</p> ]]></content:encoded>
            <category><![CDATA[HTTP2]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Server Push]]></category>
            <guid isPermaLink="false">4z1Btq5Q3lFHwOHSsHQG6n</guid>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
        <item>
            <title><![CDATA[Using HTTP/2 Server Push with PHP]]></title>
            <link>https://blog.cloudflare.com/using-http-2-server-push-with-php/</link>
            <pubDate>Fri, 13 May 2016 13:11:28 GMT</pubDate>
            <description><![CDATA[ Two weeks ago CloudFlare announced that it was supporting HTTP/2 Server Push for all our customers. By simply adding a Link header to an HTTP response specifying preload CloudFlare would automatically push items to web browsers that support Server Push. ]]></description>
            <content:encoded><![CDATA[ <p>Two weeks ago CloudFlare announced that it was supporting <a href="/announcing-support-for-http-2-server-push-2/">HTTP/2 Server</a> Push for all our customers. By simply adding a <code>Link</code> header to an HTTP response specifying <code>preload</code> CloudFlare would automatically push items to web browsers that support Server Push.</p><p>To illustrate how easy this is I create a small PHP page that uses the PHP <a href="https://secure.php.net/manual/en/function.header.php"><code>header</code></a> function to insert appropriate <code>Link</code> headers to push images to the web browser via CloudFlare. The web page looks like this when loaded:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2KEen2kNGsrXXEKZZnQSni/27615c7b083c1aff54f087eb5225c1c6/Screen-Shot-2016-05-13-at-11-50-00-AM.png" />
            
            </figure><p>There are two images loaded from the same server both of which are pushed if the web browser supports Server Push. This is achieved by inserting two <code>Link</code> headers in the HTTP response. The response looks like:</p>
            <pre><code>HTTP/1.1 200 OK
Server: nginx/1.9.15
Date: Fri, 13 May 2016 10:52:13 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Link: &lt;/images/drucken.jpg&gt;; rel=preload; as=image
Link: &lt;/images/empire.jpg&gt;; rel=preload; as=image</code></pre>
            <p>At the bottom are the two <code>Link</code> headers corresponding to the two images on the page with the <code>rel=preload</code> directive as specified in W3C <a href="https://www.w3.org/TR/preload/#server-push-http-2">preload draft</a>.</p><p>The complete code can be found in this <a href="https://gist.github.com/jgrahamc/df91229381366105c7ff0f88c8c38485">gist</a> but the core of the code looks like this:</p>
            <pre><code>    &lt;?php
    function pushImage($uri) {
        header("Link: &lt;{$uri}&gt;; rel=preload; as=image", false);
        return &lt;&lt;&lt;HTML
    &lt;img src="{$uri}"&gt;
    HTML;
    }

    $image1 = pushImage("/images/drucken.jpg");
    $image2 = pushImage("/images/empire.jpg");
    ?&gt;

    &lt;html&gt;

    &lt;head&gt;&lt;title&gt;PHP Server Push&lt;/title&gt;&lt;/head&gt;
    &lt;body&gt;

    &lt;h1&gt;PHP Server Push&lt;/h1&gt;

    &lt;?php
    echo ccbysa($image1, "https://bit.ly/1Wu5bYx",
       "https://www.flickr.com/photos/hiperactivo/", "Javier Candeira");

    echo ccbynd($image2, "https://bit.ly/24PHue3",
        "https://www.flickr.com/photos/bobsfever/", "Robert McGoldrick");
    ?&gt;

    &lt;/body&gt;
    &lt;/html&gt;</code></pre>
            <p>Since you have to call the PHP <code>header</code> function before any output (such as HTML) has occurred the code makes two calls to a helper function called <code>pushImage</code> first. <code>pushImage</code> adds the appropriate <code>Link</code> header and returns the HTML needed to insert the actual image in the page.</p><p>Later the variables <code>$image1</code> and <code>$image2</code> (which contain the HTML needed to display the images) is inserted use two other helper functions (<code>ccbysa</code> and <code>ccbynd</code>) that add captions. Those two helper functions don't play any part in the Server Push, they just ensure that the HTML is placed correctly on the page with a caption.</p><p>Notice that the <code>Link</code> header is added as follows:</p>
            <pre><code>header("Link: &lt;{$uri}&gt;; rel=preload; as=image", false);</code></pre>
            <p>The <code>false</code> second parameter tells <code>header</code> to <i>not</i> override an existing <code>Link</code> header. With that option specified multiple <code>Link</code> headers can be added. Without it the last call to <code>pushImage</code> would win.</p>
    <div>
      <h2>Effect of Server Push</h2>
      <a href="#effect-of-server-push">
        
      </a>
    </div>
    <p>To understand the effect of Server Push on the example I used Google Chrome Canary and loaded the page twice (once without the <code>Link</code> headers so that no push would occur and once with).</p><p>Here's the simple waterfall over HTTP/2 with no Server Push:</p>
            <figure>
            <a href="http://staging.blog.mrk.cfdata.org/content/images/2016/05/Screen-Shot-2016-05-13-at-12-22-24-PM.png">
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5oN4WtS0666At1eTeB2Xkr/aa2a06fb0da68d4e5a068a944c1c6da9/Screen-Shot-2016-05-13-at-12-22-24-PM.png" />
            </a>
            </figure><p>The page load time was 651ms. You can see the initial page HTML load in 175ms followed by the two images.</p><p>How here's the waterfall with HTTP/2 Server Push:</p>
            <figure>
            <a href="http://staging.blog.mrk.cfdata.org/content/images/2016/05/Screen-Shot-2016-05-13-at-12-20-58-PM.png">
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2thpvABMv76ref5uY2LIhX/771d0c7d56cec749b84306fbbdd48ca7/Screen-Shot-2016-05-13-at-12-20-58-PM.png" />
            </a>
            </figure><p>The page load time was 251ms (the HTML loaded in 168ms) and Chrome is showing that the two images were pushed (see the Initiator column).</p><p>It's not 100% obvious what happened there but digging into chrome://net-internals/ it's possible to see a detailed HTTP/2 timeline. I've edited out a few details of the protocol (such as the window size changes) to focus in on the requests and responses.</p><p>The <code>t</code> value gives the tick time (1ms per tick).</p>
            <pre><code>t=910212 [st=   1]    HTTP2_SESSION_SEND_HEADERS
                      --&gt; exclusive = true
                      --&gt; fin = true
                      --&gt; has_priority = true
                      --&gt; :method: GET
                          :scheme: https
                          :path: /index.php
                          pragma: no-cache
                          cache-control: no-cache
                          upgrade-insecure-requests: 1
                          accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
                          accept-encoding: gzip, deflate, sdch, br
                          accept-language: en-US,en;q=0.8
                          cookie: [52 bytes were stripped]
                      --&gt; parent_stream_id = 0
                      --&gt; priority = 0
                      --&gt; stream_id = 1

[...]

t=910404 [st= 193]    HTTP2_SESSION_RECV_HEADERS
                      --&gt; fin = false
                      --&gt; :status: 200
                          date: Fri, 13 May 2016 11:28:16 GMT
                          content-type: text/html
                          content-encoding: gzip
                      --&gt; stream_id = 1
t=910405 [st= 194]    HTTP2_SESSION_RECV_PUSH_PROMISE
                      --&gt; :method: GET
                          :path: /images/drucken.jpg
                          :scheme: https
                          accept-encoding: gzip, deflate, sdch, br
                      --&gt; id = 1
                      --&gt; promised_stream_id = 2
t=910405 [st= 194]    HTTP2_SESSION_RECV_PUSH_PROMISE
                      --&gt; :method: GET
                          :path: /images/empire.jpg
                          :scheme: https
                          accept-encoding: gzip, deflate, sdch, br
                      --&gt; id = 1
                      --&gt; promised_stream_id = 4
t=910405 [st= 194]    HTTP2_SESSION_RECV_DATA
                      --&gt; fin = false
                      --&gt; size = 298
                      --&gt; stream_id = 1
t=910405 [st= 194]    HTTP2_SESSION_RECV_DATA
                      --&gt; fin = true
                      --&gt; size = 0
                      --&gt; stream_id = 1
t=910409 [st= 198]    HTTP2_SESSION_RECV_HEADERS
                      --&gt; fin = false
                      --&gt; :status: 200
                          date: Fri, 13 May 2016 11:28:16 GMT
                          content-type: image/jpeg
                          content-length: 49852
                          set-cookie: [124 bytes were stripped]
                          etag: "5735aac0-12f99"
                          last-modified: Fri, 13 May 2016 10:21:52 GMT
                          cf-cache-status: HIT
                          vary: Accept-Encoding
                          expires: Fri, 13 May 2016 15:28:16 GMT
                          cache-control: public, max-age=14400
                          accept-ranges: bytes
                          server: cloudflare-nginx
                      --&gt; stream_id = 2
t=910409 [st= 198]    HTTP2_SESSION_RECV_DATA
                      --&gt; fin = false
                      --&gt; size = 987
                      --&gt; stream_id = 2
t=910409 [st= 198]    HTTP2_SESSION_RECV_DATA
                      --&gt; fin = false
                      --&gt; size = 1369
                      --&gt; stream_id = 2
t=910410 [st= 199]    HTTP2_SESSION_RECV_DATA
                      --&gt; fin = false
                      --&gt; size = 1369
                      --&gt; stream_id = 2</code></pre>
            <p>The web browser sends an <code>HTTP2_SESSION_SEND_HEADERS</code> request asking for the web page (that's the first item above) and subsequently receives the response headers and page followed immediately by two push promises for the two images. It then immediately starts receiving image data (see the <code>stream_id</code> 2).</p><p>CloudFlare's web server is pushing the image contents before the browser asked for them. When CloudFlare pushes an item specified in a <code>Link</code> header the header itself is stripped (to prevent the browser from re-requesting the resource).</p>
    <div>
      <h2>The Future Starts Here</h2>
      <a href="#the-future-starts-here">
        
      </a>
    </div>
    <p>We released HTTP/2 Server Push support to help kick start innovative use of this critical feature of HTTP/2. We would love people to start experimenting with it to see how much of a speed improvement is possible with their specific websites.</p><p>As can be seen from this blog post making use of Server Push in a web application is easy: just insert <code>Link</code> headers with the appropriate format. Server Push will be particularly fast if the items being pushed are also stored in CloudFlare's cache (as was the case with the examples above).</p><p>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).</p> ]]></content:encoded>
            <category><![CDATA[HTTP2]]></category>
            <category><![CDATA[Server Push]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">3nkrcgnTrCQJfUc4OyxsDC</guid>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
    </channel>
</rss>