summaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/net/http2/h2demo/h2demo.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/net/http2/h2demo/h2demo.go')
-rw-r--r--vendor/golang.org/x/net/http2/h2demo/h2demo.go96
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