golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/blog/content/h2push.article (about)

     1  HTTP/2 Server Push
     2  24 Mar 2017
     3  Tags: http, technical
     4  
     5  Jaana Burcu Dogan, Tom Bergan
     6  
     7  * Introduction
     8  
     9  HTTP/2 is designed to address many of the failings of HTTP/1.x.
    10  Modern web pages use many resources: HTML, stylesheets,
    11  scripts, images, and so on. In HTTP/1.x, each of these resources must
    12  be requested explicitly. This can be a slow process.
    13  The browser starts by fetching the HTML, then learns of more resources
    14  incrementally as it parses and evaluates the page. Since the server
    15  must wait for the browser to make each request, the network is often
    16  idle and underutilized.
    17  
    18  To improve latency, HTTP/2 introduced _server_push_, which allows the
    19  server to push resources to the browser before they are explicitly
    20  requested. A server often knows many of the additional resources a
    21  page will need and can start pushing those resources as it responds
    22  to the initial request. This allows the server to fully utilize an
    23  otherwise idle network and improve page load times.
    24  
    25  .image h2push/serverpush.svg _ 600
    26  
    27  At the protocol level, HTTP/2 server push is driven by `PUSH_PROMISE`
    28  frames. A `PUSH_PROMISE` describes a request that the server predicts the
    29  browser will make in the near future. As soon as the browser receives
    30  a `PUSH_PROMISE`, it knows that the server will deliver the resource.
    31  If the browser later discovers that it needs this resource, it will
    32  wait for the push to complete rather than sending a new request.
    33  This reduces the time the browser spends waiting on the network.
    34  
    35  * Server Push in net/http
    36  
    37  Go 1.8 introduced support for pushing responses from an [[https://golang.org/pkg/net/http/#Server][`http.Server`]].
    38  This feature is available if the running server is an HTTP/2 server
    39  and the incoming connection uses HTTP/2. In any HTTP handler,
    40  you can assert if the http.ResponseWriter supports server push by checking
    41  if it implements the new [[https://golang.org/pkg/net/http/#Pusher][`http.Pusher`]] interface.
    42  
    43  For example, if the server knows that `app.js` will be required to
    44  render the page, the handler can initiate a push if `http.Pusher`
    45  is available:
    46  
    47  .code h2push/pusher.go /START/,/END/
    48  
    49  The Push call creates a synthetic request for `/app.js`,
    50  synthesizes that request into a `PUSH_PROMISE` frame, then forwards
    51  the synthetic request to the server's request handler, which will
    52  generate the pushed response. The second argument to Push specifies
    53  additional headers to include in the `PUSH_PROMISE`. For example,
    54  if the response to `/app.js` varies on Accept-Encoding,
    55  then the `PUSH_PROMISE` should include an Accept-Encoding value:
    56  
    57  .code h2push/pusher.go /START1/,/END1/
    58  
    59  A fully working example is available at:
    60  
    61      $ go get golang.org/x/blog/content/h2push/server
    62  
    63  
    64  If you run the server and load [[https://localhost:8080][https://localhost:8080]],
    65  your browser's developer tools should show that `app.js` and
    66  `style.css` were pushed by the server.
    67  
    68  .image h2push/networktimeline.png _ 605
    69  
    70  * Start Your Pushes Before You Respond
    71  
    72  It's a good idea to call the Push method before sending any bytes
    73  of the response. Otherwise it is possible to accidentally generate
    74  duplicate responses. For example, suppose you write part of an HTML
    75  response:
    76  
    77  
    78      <html>
    79      <head>
    80          <link rel="stylesheet" href="a.css">...
    81  
    82  
    83  Then you call Push("a.css", nil). The browser may parse this fragment
    84  of HTML before it receives your PUSH_PROMISE, in which case the browser
    85  will send a request for `a.css` in addition to receiving your
    86  `PUSH_PROMISE`. Now the server will generate two responses for `a.css`.
    87  Calling Push before writing the response avoids this possibility entirely.
    88  
    89  * When To Use Server Push
    90  
    91  Consider using server push any time your network link is idle.
    92  Just finished sending the HTML for your web app? Don't waste time waiting,
    93  start pushing the resources your client will need. Are you inlining
    94  resources into your HTML file to reduce latency? Instead of inlining,
    95  try pushing. Redirects are another good time to use push because there
    96  is almost always a wasted round trip while the client follows the redirect.
    97  There are many possible scenarios for using push -- we are only getting started.
    98  
    99  We would be remiss if we did not mention a few caveats. First, you can only
   100  push resources your server is authoritative for -- this means you cannot
   101  push resources that are hosted on third-party servers or CDNs. Second,
   102  don't push resources unless you are confident they are actually needed
   103  by the client, otherwise your push wastes bandwidth. A corollary is to
   104  avoid pushing resources when it's likely that the client already has
   105  those resources cached. Third, the naive approach of pushing all
   106  resources on your page often makes performance worse. When in doubt, measure.
   107  
   108  The following links make for good supplemental reading:
   109  
   110  - [[https://calendar.perfplanet.com/2016/http2-push-the-details/][HTTP/2 Push: The Details]]
   111  - [[https://www.igvita.com/2013/06/12/innovating-with-http-2.0-server-push/][Innovating with HTTP/2 Server Push]]
   112  - [[https://github.com/h2o/h2o/issues/421][Cache-Aware Server Push in H2O]]
   113  - [[https://developers.google.com/web/fundamentals/performance/prpl-pattern/][The PRPL Pattern]]
   114  - [[https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXjqKGsCVNYHyLEXIxYMv0][Rules of Thumb for HTTP/2 Push]]
   115  - [[https://tools.ietf.org/html/rfc7540#section-8.2][Server Push in the HTTP/2 spec]]
   116  
   117  * Conclusion
   118  
   119  With Go 1.8, the standard library provides out-of-the-box support for HTTP/2
   120  Server Push, giving you more flexibility to optimize your web applications.
   121  
   122  Go to our [[https://http2.golang.org/serverpush][HTTP/2 Server Push demo]]
   123  page to see it in action.