Commit d9e3f127 authored by Jaana Burcu Dogan's avatar Jaana Burcu Dogan

http2/h2demo: add demo for HTTP/2 Server Push

In this demo, it takes almost twice as much to load
all items on a page without HTTP/2 Server Push.

Change-Id: Ie5c9814c4dcf9ff9f21ed215d4eb58d108715f50
Reviewed-on: https://go-review.googlesource.com/38657
Run-TryBot: Jaana Burcu Dogan <jbd@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarTom Bergan <tombergan@google.com>
parent 6c232525
...@@ -87,6 +87,7 @@ href="https://golang.org/s/http2bug">file a bug</a>.</p> ...@@ -87,6 +87,7 @@ href="https://golang.org/s/http2bug">file a bug</a>.</p>
<li>GET <a href="/reqinfo">/reqinfo</a> to dump the request + headers received</li> <li>GET <a href="/reqinfo">/reqinfo</a> to dump the request + headers received</li>
<li>GET <a href="/clockstream">/clockstream</a> streams the current time every second</li> <li>GET <a href="/clockstream">/clockstream</a> streams the current time every second</li>
<li>GET <a href="/gophertiles">/gophertiles</a> to see a page with a bunch of images</li> <li>GET <a href="/gophertiles">/gophertiles</a> to see a page with a bunch of images</li>
<li>GET <a href="/serverpush">/serverpush</a> to see a page with server push</li>
<li>GET <a href="/file/gopher.png">/file/gopher.png</a> for a small file (does If-Modified-Since, Content-Range, etc)</li> <li>GET <a href="/file/gopher.png">/file/gopher.png</a> for a small file (does If-Modified-Since, Content-Range, etc)</li>
<li>GET <a href="/file/go.src.tar.gz">/file/go.src.tar.gz</a> for a larger file (~10 MB)</li> <li>GET <a href="/file/go.src.tar.gz">/file/go.src.tar.gz</a> for a larger file (~10 MB)</li>
<li>GET <a href="/redirect">/redirect</a> to redirect back to / (this page)</li> <li>GET <a href="/redirect">/redirect</a> to redirect back to / (this page)</li>
...@@ -168,8 +169,11 @@ var ( ...@@ -168,8 +169,11 @@ var (
// fileServer returns a file-serving handler that proxies URL. // fileServer returns a file-serving handler that proxies URL.
// It lazily fetches URL on the first access and caches its contents forever. // It lazily fetches URL on the first access and caches its contents forever.
func fileServer(url string) http.Handler { func fileServer(url string, latency time.Duration) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if latency > 0 {
time.Sleep(latency)
}
hi, err := fsGrp.Do(url, func() (interface{}, error) { hi, err := fsGrp.Do(url, func() (interface{}, error) {
fsMu.Lock() fsMu.Lock()
if h, ok := fsCache[url]; ok { if h, ok := fsCache[url]; ok {
...@@ -249,12 +253,17 @@ func registerHandlers() { ...@@ -249,12 +253,17 @@ func registerHandlers() {
mux2.ServeHTTP(w, r) mux2.ServeHTTP(w, r)
}) })
mux2.HandleFunc("/", home) mux2.HandleFunc("/", home)
mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png")) mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png", 0))
mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz")) mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz", 0))
mux2.HandleFunc("/reqinfo", reqInfoHandler) mux2.HandleFunc("/reqinfo", reqInfoHandler)
mux2.HandleFunc("/crc32", crcHandler) mux2.HandleFunc("/crc32", crcHandler)
mux2.HandleFunc("/ECHO", echoCapitalHandler) mux2.HandleFunc("/ECHO", echoCapitalHandler)
mux2.HandleFunc("/clockstream", clockStreamHandler) mux2.HandleFunc("/clockstream", clockStreamHandler)
mux2.HandleFunc("/serverpush", pushHandler)
mux2.Handle("/serverpush/static/jquery.min.js", fileServer("https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js", 100*time.Millisecond))
mux2.Handle("/serverpush/static/godocs.js", fileServer("https://golang.org/lib/godoc/godocs.js", 100*time.Millisecond))
mux2.Handle("/serverpush/static/playground.js", fileServer("https://golang.org/lib/godoc/playground.js", 100*time.Millisecond))
mux2.Handle("/serverpush/static/style.css", fileServer("https://golang.org/lib/godoc/style.css", 100*time.Millisecond))
mux2.Handle("/gophertiles", tiles) mux2.Handle("/gophertiles", tiles)
mux2.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) { mux2.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
...@@ -267,6 +276,37 @@ func registerHandlers() { ...@@ -267,6 +276,37 @@ func registerHandlers() {
}) })
} }
var pushResources = []string{
"/serverpush/static/jquery.min.js",
"/serverpush/static/godocs.js",
"/serverpush/static/playground.js",
"/serverpush/static/style.css",
}
func pushHandler(w http.ResponseWriter, r *http.Request) {
cacheBust := time.Now().UnixNano()
if pusher, ok := w.(http.Pusher); ok {
for _, resource := range pushResources {
url := fmt.Sprintf("%s?%d", resource, cacheBust)
if err := pusher.Push(url, nil); err != nil {
log.Printf("Failed to push %v: %v", resource, err)
}
}
}
time.Sleep(100 * time.Millisecond) // fake network latency + parsing time
if err := pushTmpl.Execute(w, struct {
CacheBust int64
HTTPSHost string
HTTPHost string
}{
CacheBust: cacheBust,
HTTPSHost: httpsHost(),
HTTPHost: httpHost(),
}); err != nil {
log.Printf("Executing server push template: %v", err)
}
}
func newGopherTilesHandler() http.Handler { func newGopherTilesHandler() http.Handler {
const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg" const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg"
res, err := http.Get(gopherURL) res, err := http.Get(gopherURL)
...@@ -393,7 +433,11 @@ func serveProdTLS() error { ...@@ -393,7 +433,11 @@ func serveProdTLS() error {
GetCertificate: m.GetCertificate, GetCertificate: m.GetCertificate,
}, },
} }
http2.ConfigureServer(srv, &http2.Server{}) http2.ConfigureServer(srv, &http2.Server{
NewWriteScheduler: func() http2.WriteScheduler {
return http2.NewPriorityWriteScheduler(nil)
},
})
ln, err := net.Listen("tcp", ":443") ln, err := net.Listen("tcp", ":443")
if err != nil { if err != nil {
return err return err
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment