diff options
Diffstat (limited to 'vendor/golang.org/x/net/http2/h2demo/h2demo.go')
-rw-r--r-- | vendor/golang.org/x/net/http2/h2demo/h2demo.go | 96 |
1 files changed, 63 insertions, 33 deletions
diff --git a/vendor/golang.org/x/net/http2/h2demo/h2demo.go b/vendor/golang.org/x/net/http2/h2demo/h2demo.go index fa5978ee5..9853107b9 100644 --- a/vendor/golang.org/x/net/http2/h2demo/h2demo.go +++ b/vendor/golang.org/x/net/http2/h2demo/h2demo.go @@ -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="/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="/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/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> @@ -168,8 +169,11 @@ var ( // fileServer returns a file-serving handler that proxies URL. // 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) { + if latency > 0 { + time.Sleep(latency) + } hi, err := fsGrp.Do(url, func() (interface{}, error) { fsMu.Lock() if h, ok := fsCache[url]; ok { @@ -227,14 +231,18 @@ func clockStreamHandler(w http.ResponseWriter, r *http.Request) { func registerHandlers() { tiles := newGopherTilesHandler() + push := newPushHandler() mux2 := http.NewServeMux() http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - if r.TLS == nil { - if r.URL.Path == "/gophertiles" { - tiles.ServeHTTP(w, r) - return - } + switch { + case r.URL.Path == "/gophertiles": + tiles.ServeHTTP(w, r) // allow HTTP/2 + HTTP/1.x + return + case strings.HasPrefix(r.URL.Path, "/serverpush"): + push.ServeHTTP(w, r) // allow HTTP/2 + HTTP/1.x + return + case r.TLS == nil: // do not allow HTTP/1.x for anything else http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound) return } @@ -249,8 +257,8 @@ func registerHandlers() { mux2.ServeHTTP(w, r) }) mux2.HandleFunc("/", home) - mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png")) - mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz")) + 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", 0)) mux2.HandleFunc("/reqinfo", reqInfoHandler) mux2.HandleFunc("/crc32", crcHandler) mux2.HandleFunc("/ECHO", echoCapitalHandler) @@ -267,6 +275,46 @@ func registerHandlers() { }) } +var pushResources = map[string]http.Handler{ + "/serverpush/static/jquery.min.js": fileServer("https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js", 100*time.Millisecond), + "/serverpush/static/godocs.js": fileServer("https://golang.org/lib/godoc/godocs.js", 100*time.Millisecond), + "/serverpush/static/playground.js": fileServer("https://golang.org/lib/godoc/playground.js", 100*time.Millisecond), + "/serverpush/static/style.css": fileServer("https://golang.org/lib/godoc/style.css", 100*time.Millisecond), +} + +func newPushHandler() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + for path, handler := range pushResources { + if r.URL.Path == path { + handler.ServeHTTP(w, r) + return + } + } + + cacheBust := time.Now().UnixNano() + if pusher, ok := w.(http.Pusher); ok { + for path := range pushResources { + url := fmt.Sprintf("%s?%d", path, cacheBust) + if err := pusher.Push(url, nil); err != nil { + log.Printf("Failed to push %v: %v", path, 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 { const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg" res, err := http.Get(gopherURL) @@ -313,13 +361,6 @@ func newGopherTilesHandler() http.Handler { } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ms, _ := strconv.Atoi(r.FormValue("latency")) - push, _ := strconv.ParseBool(r.FormValue("push")) - - cacheBust := time.Now().UnixNano() - if push { - pushTiles(w, cacheBust, ms, xt, yt) - } - const nanosPerMilli = 1e6 if r.FormValue("x") != "" { x, _ := strconv.Atoi(r.FormValue("x")) @@ -336,13 +377,13 @@ func newGopherTilesHandler() http.Handler { fmt.Fprintf(w, "A grid of %d tiled images is below. Compare:<p>", xt*yt) for _, ms := range []int{0, 30, 200, 1000} { d := time.Duration(ms) * nanosPerMilli - fmt.Fprintf(w, "[<a href='https://%s/gophertiles?latency=%d'>HTTP/2, %v latency</a>] [<a href='https://%s/gophertiles?latency=%d&push=true'>HTTP/2, %v latency with Server Push</a>] [<a href='http://%s/gophertiles?latency=%d'>HTTP/1, %v latency</a>]<br>\n", - httpsHost(), ms, d, + fmt.Fprintf(w, "[<a href='https://%s/gophertiles?latency=%d'>HTTP/2, %v latency</a>] [<a href='http://%s/gophertiles?latency=%d'>HTTP/1, %v latency</a>]<br>\n", httpsHost(), ms, d, httpHost(), ms, d, ) } io.WriteString(w, "<p>\n") + cacheBust := time.Now().UnixNano() for y := 0; y < yt; y++ { for x := 0; x < xt; x++ { fmt.Fprintf(w, "<img width=%d height=%d src='/gophertiles?x=%d&y=%d&cachebust=%d&latency=%d'>", @@ -363,21 +404,6 @@ function showtimes() { }) } -func pushTiles(w http.ResponseWriter, cacheBust int64, latency int, xt, yt int) { - pusher, ok := w.(http.Pusher) - if !ok { - return - } - for y := 0; y < yt; y++ { - for x := 0; x < xt; x++ { - img := fmt.Sprintf("/gophertiles?x=%d&y=%d&cachebust=%d&latency=%d", x, y, cacheBust, latency) - if err := pusher.Push(img, nil); err != nil { - log.Printf("Failed to push %v: %v", img, err) - } - } - } -} - func httpsHost() string { if *hostHTTPS != "" { return *hostHTTPS @@ -415,7 +441,11 @@ func serveProdTLS() error { 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") if err != nil { return err |