aboutsummaryrefslogtreecommitdiff
path: root/content/h2push.article
diff options
context:
space:
mode:
Diffstat (limited to 'content/h2push.article')
1 files changed, 123 insertions, 0 deletions
diff --git a/content/h2push.article b/content/h2push.article
new file mode 100644
index 0000000..9079f8d
--- /dev/null
+++ b/content/h2push.article
@@ -0,0 +1,123 @@
+HTTP/2 Server Push
+24 Mar 2017
+Tags: http, technical
+
+Jaana Burcu Dogan, Tom Bergan
+
+* Introduction
+
+HTTP/2 is designed to address many of the failings of HTTP/1.x.
+Modern web pages use many resources: HTML, stylesheets,
+scripts, images, and so on. In HTTP/1.x, each of these resources must
+be requested explicitly. This can be a slow process.
+The browser starts by fetching the HTML, then learns of more resources
+incrementally as it parses and evaluates the page. Since the server
+must wait for the browser to make each request, the network is often
+idle and underutilized.
+
+To improve latency, HTTP/2 introduced _server_push_, which allows the
+server to push resources to the browser before they are explicitly
+requested. A server often knows many of the additional resources a
+page will need and can start pushing those resources as it responds
+to the initial request. This allows the server to fully utilize an
+otherwise idle network and improve page load times.
+
+.image h2push/serverpush.svg _ 600
+
+At the protocol level, HTTP/2 server push is driven by `PUSH_PROMISE`
+frames. A `PUSH_PROMISE` describes a request that the server predicts the
+browser will make in the near future. As soon as the browser receives
+a `PUSH_PROMISE`, it knows that the server will deliver the resource.
+If the browser later discovers that it needs this resource, it will
+wait for the push to complete rather than sending a new request.
+This reduces the time the browser spends waiting on the network.
+
+* Server Push in net/http
+
+Go 1.8 introduced support for pushing responses from an [[https://golang.org/pkg/net/http/#Server][`http.Server`]].
+This feature is available if the running server is an HTTP/2 server
+and the incoming connection uses HTTP/2. In any HTTP handler,
+you can assert if the http.ResponseWriter supports server push by checking
+if it implements the new [[https://golang.org/pkg/net/http/#Pusher][`http.Pusher`]] interface.
+
+For example, if the server knows that `app.js` will be required to
+render the page, the handler can initiate a push if `http.Pusher`
+is available:
+
+.code h2push/pusher.go /START/,/END/
+
+The Push call creates a synthetic request for `/app.js`,
+synthesizes that request into a `PUSH_PROMISE` frame, then forwards
+the synthetic request to the server's request handler, which will
+generate the pushed response. The second argument to Push specifies
+additional headers to include in the `PUSH_PROMISE`. For example,
+if the response to `/app.js` varies on Accept-Encoding,
+then the `PUSH_PROMISE` should include an Accept-Encoding value:
+
+.code h2push/pusher.go /START1/,/END1/
+
+A fully working example is available at:
+
+ $ go get golang.org/x/blog/content/h2push/server
+
+
+If you run the server and load [[https://localhost:8080][https://localhost:8080]],
+your browser's developer tools should show that `app.js` and
+`style.css` were pushed by the server.
+
+.image h2push/networktimeline.png _ 605
+
+* Start Your Pushes Before You Respond
+
+It's a good idea to call the Push method before sending any bytes
+of the response. Otherwise it is possible to accidentally generate
+duplicate responses. For example, suppose you write part of an HTML
+response:
+
+
+ <html>
+ <head>
+ <link rel="stylesheet" href="a.css">...
+
+
+Then you call Push("a.css", nil). The browser may parse this fragment
+of HTML before it receives your PUSH_PROMISE, in which case the browser
+will send a request for `a.css` in addition to receiving your
+`PUSH_PROMISE`. Now the server will generate two responses for `a.css`.
+Calling Push before writing the response avoids this possibility entirely.
+
+* When To Use Server Push
+
+Consider using server push any time your network link is idle.
+Just finished sending the HTML for your web app? Don't waste time waiting,
+start pushing the resources your client will need. Are you inlining
+resources into your HTML file to reduce latency? Instead of inlining,
+try pushing. Redirects are another good time to use push because there
+is almost always a wasted round trip while the client follows the redirect.
+There are many possible scenarios for using push -- we are only getting started.
+
+We would be remiss if we did not mention a few caveats. First, you can only
+push resources your server is authoritative for -- this means you cannot
+push resources that are hosted on third-party servers or CDNs. Second,
+don't push resources unless you are confident they are actually needed
+by the client, otherwise your push wastes bandwidth. A corollary is to
+avoid pushing resources when it's likely that the client already has
+those resources cached. Third, the naive approach of pushing all
+resources on your page often makes performance worse. When in doubt, measure.
+
+The following links make for good supplemental reading:
+
+- [[https://calendar.perfplanet.com/2016/http2-push-the-details/][HTTP/2 Push: The Details]]
+- [[https://www.igvita.com/2013/06/12/innovating-with-http-2.0-server-push/][Innovating with HTTP/2 Server Push]]
+- [[https://github.com/h2o/h2o/issues/421][Cache-Aware Server Push in H2O]]
+- [[https://developers.google.com/web/fundamentals/performance/prpl-pattern/][The PRPL Pattern]]
+- [[https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXjqKGsCVNYHyLEXIxYMv0][Rules of Thumb for HTTP/2 Push]]
+- [[https://tools.ietf.org/html/rfc7540#section-8.2][Server Push in the HTTP/2 spec]]
+
+* Conclusion
+
+With Go 1.8, the standard library provides out-of-the-box support for HTTP/2
+Server Push, giving you more flexibility to optimize your web applications.
+
+Go to our [[https://http2.golang.org/serverpush][HTTP/2 Server Push demo]]
+page to see it in action.