http2/h2demo: fix the HTTP/1-vs-HTTP/2 demo after HSTS breakage
We were previously demoing HTTP/1 vs HTTP/2 loading performance using
http:// scheme (which uses HTTP/1 implicitly) on the http2.golang.org
domain for HTTP/1, and https://http2.golang.org for HTTP/2.
But then golang.org got into the HSTS preload list, forcing all
*.golang.org to only be HTTPS.
So now, rather than find a new base domain name, to compare against
HTTP/1 we instead use https://http1.golang.org/ and then use the SNI
name to determine whether we advertise "h2".
Also, some cleanup:
* remove launch.go; it's no longer used since we moved to kubernetes
* use a multi-stage Dockerfile rather than the hacky workarounds
that used to be necessary to simulate multiple stages
* modernize the kubernetes deployment stuff to match how we do
it elsewhere ("gcloud docker" is long deprecated too)
* update from Go 1.9 to Go 1.11 for the prod base
Fixes golang/go#30033
Change-Id: I9f6b1f496d4005e5a08bf990843d440005a5b3e8
Reviewed-on: https://go-review.googlesource.com/c/160857
Reviewed-by: Andrew Bonventre <andybons@golang.org>
diff --git a/http2/h2demo/Dockerfile b/http2/h2demo/Dockerfile
index 9238673..91f73ff 100644
--- a/http2/h2demo/Dockerfile
+++ b/http2/h2demo/Dockerfile
@@ -2,10 +2,162 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
-FROM scratch
+FROM golang:1.11 AS build
LABEL maintainer "golang-dev@googlegroups.com"
-COPY ca-certificates.crt /etc/ssl/certs/
-COPY h2demo /
-ENTRYPOINT ["/h2demo", "-prod"]
+# BEGIN deps (run `make update-deps` to update)
+
+# Repo cloud.google.com/go at b5eca92 (2018-10-23)
+ENV REV=b5eca92245a08e245bc29c4880c9779ea4aeaa9a
+RUN go get -d cloud.google.com/go/compute/metadata `#and 7 other pkgs` &&\
+ (cd /go/src/cloud.google.com/go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo github.com/golang/protobuf at b4deda0 (2018-04-30)
+ENV REV=b4deda0973fb4c70b50d226b1af49f3da59f5265
+RUN go get -d github.com/golang/protobuf/proto `#and 6 other pkgs` &&\
+ (cd /go/src/github.com/golang/protobuf && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo github.com/googleapis/gax-go at 317e000 (2017-09-15)
+ENV REV=317e0006254c44a0ac427cc52a0e083ff0b9622f
+RUN go get -d github.com/googleapis/gax-go &&\
+ (cd /go/src/github.com/googleapis/gax-go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo go.opencensus.io at ebd8d31 (2018-05-16)
+ENV REV=ebd8d31470fedf6c27d0e3056653ddff642509b8
+RUN go get -d go.opencensus.io/internal `#and 11 other pkgs` &&\
+ (cd /go/src/go.opencensus.io && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo go4.org at fba789b (2018-01-03)
+ENV REV=fba789b7e39ba524b9e60c45c37a50fae63a2a09
+RUN go get -d go4.org/syncutil/singleflight &&\
+ (cd /go/src/go4.org && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/build at 193361e (2019-02-01)
+ENV REV=193361e263a8c4175cbb6769bb2a59d8c4f8183e
+RUN go get -d golang.org/x/build/autocertcache &&\
+ (cd /go/src/golang.org/x/build && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/crypto at c7b33c3 (2019-01-28)
+ENV REV=c7b33c32a30bae9ba07d37eb4d86f1f8b0f644fb
+RUN go get -d golang.org/x/crypto/acme `#and 2 other pkgs` &&\
+ (cd /go/src/golang.org/x/crypto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/oauth2 at c6d9d57 (2019-01-18)
+ENV REV=c6d9d5723bcdfb8ec25b90ea254cffe6025386d6
+RUN go get -d golang.org/x/oauth2 `#and 5 other pkgs` &&\
+ (cd /go/src/golang.org/x/oauth2 && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/sys at 4d1cda0 (2018-12-13)
+ENV REV=4d1cda033e0619309c606fc686de3adcf599539e
+RUN go get -d golang.org/x/sys/unix &&\
+ (cd /go/src/golang.org/x/sys && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/text at 6f44c5a (2018-10-30)
+ENV REV=6f44c5a2ea40ee3593d98cdcc905cc1fdaa660e2
+RUN go get -d golang.org/x/text/secure/bidirule `#and 4 other pkgs` &&\
+ (cd /go/src/golang.org/x/text && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/api at 41dc4b6 (2018-12-17)
+ENV REV=41dc4b66e69d5dbf20efe4ba67e19d214d147ae3
+RUN go get -d google.golang.org/api/gensupport `#and 10 other pkgs` &&\
+ (cd /go/src/google.golang.org/api && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/genproto at 86e600f (2018-04-27)
+ENV REV=86e600f69ee4704c6efbf6a2a40a5c10700e76c2
+RUN go get -d google.golang.org/genproto/googleapis/api/annotations `#and 4 other pkgs` &&\
+ (cd /go/src/google.golang.org/genproto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/grpc at 07ef407 (2018-08-06)
+ENV REV=07ef407d991f1004e6c3367c8f452ed9a02f17ff
+RUN go get -d google.golang.org/grpc `#and 26 other pkgs` &&\
+ (cd /go/src/google.golang.org/grpc && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Optimization to speed up iterative development, not necessary for correctness:
+RUN go install cloud.google.com/go/compute/metadata \
+ cloud.google.com/go/iam \
+ cloud.google.com/go/internal \
+ cloud.google.com/go/internal/optional \
+ cloud.google.com/go/internal/trace \
+ cloud.google.com/go/internal/version \
+ cloud.google.com/go/storage \
+ github.com/golang/protobuf/proto \
+ github.com/golang/protobuf/protoc-gen-go/descriptor \
+ github.com/golang/protobuf/ptypes \
+ github.com/golang/protobuf/ptypes/any \
+ github.com/golang/protobuf/ptypes/duration \
+ github.com/golang/protobuf/ptypes/timestamp \
+ github.com/googleapis/gax-go \
+ go.opencensus.io/internal \
+ go.opencensus.io/internal/tagencoding \
+ go.opencensus.io/plugin/ochttp \
+ go.opencensus.io/plugin/ochttp/propagation/b3 \
+ go.opencensus.io/stats \
+ go.opencensus.io/stats/internal \
+ go.opencensus.io/stats/view \
+ go.opencensus.io/tag \
+ go.opencensus.io/trace \
+ go.opencensus.io/trace/internal \
+ go.opencensus.io/trace/propagation \
+ go4.org/syncutil/singleflight \
+ golang.org/x/build/autocertcache \
+ golang.org/x/crypto/acme \
+ golang.org/x/crypto/acme/autocert \
+ golang.org/x/oauth2 \
+ golang.org/x/oauth2/google \
+ golang.org/x/oauth2/internal \
+ golang.org/x/oauth2/jws \
+ golang.org/x/oauth2/jwt \
+ golang.org/x/sys/unix \
+ golang.org/x/text/secure/bidirule \
+ golang.org/x/text/transform \
+ golang.org/x/text/unicode/bidi \
+ golang.org/x/text/unicode/norm \
+ google.golang.org/api/gensupport \
+ google.golang.org/api/googleapi \
+ google.golang.org/api/googleapi/internal/uritemplates \
+ google.golang.org/api/googleapi/transport \
+ google.golang.org/api/internal \
+ google.golang.org/api/iterator \
+ google.golang.org/api/option \
+ google.golang.org/api/storage/v1 \
+ google.golang.org/api/transport/http \
+ google.golang.org/api/transport/http/internal/propagation \
+ google.golang.org/genproto/googleapis/api/annotations \
+ google.golang.org/genproto/googleapis/iam/v1 \
+ google.golang.org/genproto/googleapis/rpc/code \
+ google.golang.org/genproto/googleapis/rpc/status \
+ google.golang.org/grpc \
+ google.golang.org/grpc/balancer \
+ google.golang.org/grpc/balancer/base \
+ google.golang.org/grpc/balancer/roundrobin \
+ google.golang.org/grpc/codes \
+ google.golang.org/grpc/connectivity \
+ google.golang.org/grpc/credentials \
+ google.golang.org/grpc/encoding \
+ google.golang.org/grpc/encoding/proto \
+ google.golang.org/grpc/grpclog \
+ google.golang.org/grpc/internal \
+ google.golang.org/grpc/internal/backoff \
+ google.golang.org/grpc/internal/channelz \
+ google.golang.org/grpc/internal/envconfig \
+ google.golang.org/grpc/internal/grpcrand \
+ google.golang.org/grpc/internal/transport \
+ google.golang.org/grpc/keepalive \
+ google.golang.org/grpc/metadata \
+ google.golang.org/grpc/naming \
+ google.golang.org/grpc/peer \
+ google.golang.org/grpc/resolver \
+ google.golang.org/grpc/resolver/dns \
+ google.golang.org/grpc/resolver/passthrough \
+ google.golang.org/grpc/stats \
+ google.golang.org/grpc/status \
+ google.golang.org/grpc/tap
+# END deps
+
+COPY . /go/src/golang.org/x/net/
+
+RUN go install -tags "h2demo netgo" golang.org/x/net/http2/h2demo
+
+FROM golang:1.11
+COPY --from=build /go/bin/h2demo /h2demo
diff --git a/http2/h2demo/Dockerfile.0 b/http2/h2demo/Dockerfile.0
deleted file mode 100644
index fd8435d..0000000
--- a/http2/h2demo/Dockerfile.0
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2018 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-FROM golang:1.9
-LABEL maintainer "golang-dev@googlegroups.com"
-
-ENV CGO_ENABLED=0
-
-# BEGIN deps (run `make update-deps` to update)
-
-# Repo cloud.google.com/go at 1d0c2da (2018-01-30)
-ENV REV=1d0c2da40456a9b47f5376165f275424acc15c09
-RUN go get -d cloud.google.com/go/compute/metadata `#and 6 other pkgs` &&\
- (cd /go/src/cloud.google.com/go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo github.com/golang/protobuf at 9255415 (2018-01-25)
-ENV REV=925541529c1fa6821df4e44ce2723319eb2be768
-RUN go get -d github.com/golang/protobuf/proto `#and 6 other pkgs` &&\
- (cd /go/src/github.com/golang/protobuf && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo github.com/googleapis/gax-go at 317e000 (2017-09-15)
-ENV REV=317e0006254c44a0ac427cc52a0e083ff0b9622f
-RUN go get -d github.com/googleapis/gax-go &&\
- (cd /go/src/github.com/googleapis/gax-go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo go4.org at 034d17a (2017-05-25)
-ENV REV=034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e
-RUN go get -d go4.org/syncutil/singleflight &&\
- (cd /go/src/go4.org && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo golang.org/x/build at 8aa9ee0 (2018-02-01)
-ENV REV=8aa9ee0e557fd49c14113e5ba106e13a5b455460
-RUN go get -d golang.org/x/build/autocertcache &&\
- (cd /go/src/golang.org/x/build && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo golang.org/x/crypto at 1875d0a (2018-01-27)
-ENV REV=1875d0a70c90e57f11972aefd42276df65e895b9
-RUN go get -d golang.org/x/crypto/acme `#and 2 other pkgs` &&\
- (cd /go/src/golang.org/x/crypto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo golang.org/x/oauth2 at 30785a2 (2018-01-04)
-ENV REV=30785a2c434e431ef7c507b54617d6a951d5f2b4
-RUN go get -d golang.org/x/oauth2 `#and 5 other pkgs` &&\
- (cd /go/src/golang.org/x/oauth2 && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo golang.org/x/text at e19ae14 (2017-12-27)
-ENV REV=e19ae1496984b1c655b8044a65c0300a3c878dd3
-RUN go get -d golang.org/x/text/secure/bidirule `#and 4 other pkgs` &&\
- (cd /go/src/golang.org/x/text && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo google.golang.org/api at 7d0e2d3 (2018-01-30)
-ENV REV=7d0e2d350555821bef5a5b8aecf0d12cc1def633
-RUN go get -d google.golang.org/api/gensupport `#and 9 other pkgs` &&\
- (cd /go/src/google.golang.org/api && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo google.golang.org/genproto at 4eb30f4 (2018-01-25)
-ENV REV=4eb30f4778eed4c258ba66527a0d4f9ec8a36c45
-RUN go get -d google.golang.org/genproto/googleapis/api/annotations `#and 3 other pkgs` &&\
- (cd /go/src/google.golang.org/genproto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Repo google.golang.org/grpc at 0bd008f (2018-01-25)
-ENV REV=0bd008f5fadb62d228f12b18d016709e8139a7af
-RUN go get -d google.golang.org/grpc `#and 23 other pkgs` &&\
- (cd /go/src/google.golang.org/grpc && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
-
-# Optimization to speed up iterative development, not necessary for correctness:
-RUN go install cloud.google.com/go/compute/metadata \
- cloud.google.com/go/iam \
- cloud.google.com/go/internal \
- cloud.google.com/go/internal/optional \
- cloud.google.com/go/internal/version \
- cloud.google.com/go/storage \
- github.com/golang/protobuf/proto \
- github.com/golang/protobuf/protoc-gen-go/descriptor \
- github.com/golang/protobuf/ptypes \
- github.com/golang/protobuf/ptypes/any \
- github.com/golang/protobuf/ptypes/duration \
- github.com/golang/protobuf/ptypes/timestamp \
- github.com/googleapis/gax-go \
- go4.org/syncutil/singleflight \
- golang.org/x/build/autocertcache \
- golang.org/x/crypto/acme \
- golang.org/x/crypto/acme/autocert \
- golang.org/x/oauth2 \
- golang.org/x/oauth2/google \
- golang.org/x/oauth2/internal \
- golang.org/x/oauth2/jws \
- golang.org/x/oauth2/jwt \
- golang.org/x/text/secure/bidirule \
- golang.org/x/text/transform \
- golang.org/x/text/unicode/bidi \
- golang.org/x/text/unicode/norm \
- google.golang.org/api/gensupport \
- google.golang.org/api/googleapi \
- google.golang.org/api/googleapi/internal/uritemplates \
- google.golang.org/api/googleapi/transport \
- google.golang.org/api/internal \
- google.golang.org/api/iterator \
- google.golang.org/api/option \
- google.golang.org/api/storage/v1 \
- google.golang.org/api/transport/http \
- google.golang.org/genproto/googleapis/api/annotations \
- google.golang.org/genproto/googleapis/iam/v1 \
- google.golang.org/genproto/googleapis/rpc/status \
- google.golang.org/grpc \
- google.golang.org/grpc/balancer \
- google.golang.org/grpc/balancer/base \
- google.golang.org/grpc/balancer/roundrobin \
- google.golang.org/grpc/codes \
- google.golang.org/grpc/connectivity \
- google.golang.org/grpc/credentials \
- google.golang.org/grpc/encoding \
- google.golang.org/grpc/encoding/proto \
- google.golang.org/grpc/grpclb/grpc_lb_v1/messages \
- google.golang.org/grpc/grpclog \
- google.golang.org/grpc/internal \
- google.golang.org/grpc/keepalive \
- google.golang.org/grpc/metadata \
- google.golang.org/grpc/naming \
- google.golang.org/grpc/peer \
- google.golang.org/grpc/resolver \
- google.golang.org/grpc/resolver/dns \
- google.golang.org/grpc/resolver/passthrough \
- google.golang.org/grpc/stats \
- google.golang.org/grpc/status \
- google.golang.org/grpc/tap \
- google.golang.org/grpc/transport
-# END deps
-
-COPY . /go/src/golang.org/x/net/
-
-RUN go install -tags "h2demo netgo" -ldflags "-linkmode=external -extldflags '-static -pthread'" golang.org/x/net/http2/h2demo
-
diff --git a/http2/h2demo/Makefile b/http2/h2demo/Makefile
index 306d198..388d8de 100644
--- a/http2/h2demo/Makefile
+++ b/http2/h2demo/Makefile
@@ -4,52 +4,34 @@
MUTABLE_VERSION ?= latest
VERSION ?= $(shell git rev-parse --short HEAD)
-
-IMAGE_STAGING := gcr.io/go-dashboard-dev/h2demo
-IMAGE_PROD := gcr.io/symbolic-datum-552/h2demo
-
-DOCKER_IMAGE_build0=build0/h2demo:latest
-DOCKER_CTR_build0=h2demo-build0
-
-build0: *.go Dockerfile.0
- docker build --force-rm -f Dockerfile.0 --tag=$(DOCKER_IMAGE_build0) ../..
-
-h2demo: build0
- docker create --name $(DOCKER_CTR_build0) $(DOCKER_IMAGE_build0)
- docker cp $(DOCKER_CTR_build0):/go/bin/$@ $@
- docker rm $(DOCKER_CTR_build0)
-
-ca-certificates.crt:
- docker create --name $(DOCKER_CTR_build0) $(DOCKER_IMAGE_build0)
- docker cp $(DOCKER_CTR_build0):/etc/ssl/certs/$@ $@
- docker rm $(DOCKER_CTR_build0)
+IMAGE_NAME=h2demo
update-deps:
go install golang.org/x/build/cmd/gitlock
- gitlock --update=Dockerfile.0 --ignore=golang.org/x/net --tags=h2demo golang.org/x/net/http2/h2demo
+ gitlock --update=Dockerfile --ignore=golang.org/x/net --tags=h2demo golang.org/x/net/http2/h2demo
-docker-prod: Dockerfile h2demo ca-certificates.crt
- docker build --force-rm --tag=$(IMAGE_PROD):$(VERSION) .
- docker tag $(IMAGE_PROD):$(VERSION) $(IMAGE_PROD):$(MUTABLE_VERSION)
-docker-staging: Dockerfile h2demo ca-certificates.crt
- docker build --force-rm --tag=$(IMAGE_STAGING):$(VERSION) .
- docker tag $(IMAGE_STAGING):$(VERSION) $(IMAGE_STAGING):$(MUTABLE_VERSION)
+docker: Dockerfile
+ go install golang.org/x/build/cmd/xb
+ xb docker build -t golang/$(IMAGE_NAME) -f Dockerfile ../..
-push-prod: docker-prod
- gcloud docker -- push $(IMAGE_PROD):$(MUTABLE_VERSION)
- gcloud docker -- push $(IMAGE_PROD):$(VERSION)
-push-staging: docker-staging
- gcloud docker -- push $(IMAGE_STAGING):$(MUTABLE_VERSION)
- gcloud docker -- push $(IMAGE_STAGING):$(VERSION)
+push-staging: docker
+ go install golang.org/x/build/cmd/xb
+ xb --staging docker tag golang/$(IMAGE_NAME) REPO/$(IMAGE_NAME):$(VERSION)
+ xb --staging docker tag golang/$(IMAGE_NAME) REPO/$(IMAGE_NAME):latest
+ xb --staging docker push REPO/$(IMAGE_NAME):$(VERSION)
+ xb --staging docker push REPO/$(IMAGE_NAME):latest
+push-prod: docker
+ go install golang.org/x/build/cmd/xb
+ xb --prod docker tag golang/$(IMAGE_NAME) REPO/$(IMAGE_NAME):$(VERSION)
+ xb --prod docker tag golang/$(IMAGE_NAME) REPO/$(IMAGE_NAME):latest
+ xb --prod docker push REPO/$(IMAGE_NAME):$(VERSION)
+ xb --prod docker push REPO/$(IMAGE_NAME):latest
+
+# TODO(bradfitz): add REPO subsitution in xb for the kubectl command.
deploy-prod: push-prod
- kubectl set image deployment/h2demo-deployment h2demo=$(IMAGE_PROD):$(VERSION)
+ xb --prod kubectl set image deployment/h2demo-deployment h2demo=gcr.io/symbolic-datum-552/h2demo:$(VERSION)
deploy-staging: push-staging
- kubectl set image deployment/h2demo-deployment h2demo=$(IMAGE_STAGING):$(VERSION)
-
-.PHONY: clean
-clean:
- $(RM) h2demo
- $(RM) ca-certificates.crt
+ xb --staging kubectl set image deployment/h2demo-deployment h2demo=gcr.io/go-dashboard-dev/h2demo:$(VERSION)
FORCE:
diff --git a/http2/h2demo/h2demo.go b/http2/h2demo/h2demo.go
index 59d9f5f..196a2a4 100644
--- a/http2/h2demo/h2demo.go
+++ b/http2/h2demo/h2demo.go
@@ -46,6 +46,10 @@
)
func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Host == "http1.golang.org" {
+ http.Redirect(w, r, "https://http2.golang.org/", http.StatusFound)
+ return
+ }
io.WriteString(w, `<html>
<body>
<h1>Go + HTTP/2</h1>
@@ -307,13 +311,13 @@
}
time.Sleep(100 * time.Millisecond) // fake network latency + parsing time
if err := pushTmpl.Execute(w, struct {
- CacheBust int64
- HTTPSHost string
- HTTPHost string
+ CacheBust int64
+ HTTPSHost string
+ HTTP1Prefix string
}{
- CacheBust: cacheBust,
- HTTPSHost: httpsHost(),
- HTTPHost: httpHost(),
+ CacheBust: cacheBust,
+ HTTPSHost: httpsHost(),
+ HTTP1Prefix: http1Prefix(),
}); err != nil {
log.Printf("Executing server push template: %v", err)
}
@@ -382,9 +386,9 @@
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='http://%s/gophertiles?latency=%d'>HTTP/1, %v latency</a>]<br>\n",
+ fmt.Fprintf(w, "[<a href='https://%s/gophertiles?latency=%d'>HTTP/2, %v latency</a>] [<a href='%s/gophertiles?latency=%d'>HTTP/1, %v latency</a>]<br>\n",
httpsHost(), ms, d,
- httpHost(), ms, d,
+ http1Prefix(), ms, d,
)
}
io.WriteString(w, "<p>\n")
@@ -420,6 +424,13 @@
}
}
+func http1Prefix() string {
+ if *prod {
+ return "https://http1.golang.org"
+ }
+ return "http://" + httpHost()
+}
+
func httpHost() string {
if *hostHTTP != "" {
return *hostHTTP
@@ -435,6 +446,14 @@
srv := &http.Server{
TLSConfig: &tls.Config{
GetCertificate: autocertManager.GetCertificate,
+ GetConfigForClient: func(hello *tls.ClientHelloInfo) (*tls.Config, error) {
+ if hello.ServerName == "http1.golang.org" {
+ return &tls.Config{
+ GetCertificate: autocertManager.GetCertificate,
+ }, nil
+ }
+ return nil, nil // fallback to other methods
+ },
},
}
http2.ConfigureServer(srv, &http2.Server{
@@ -464,7 +483,7 @@
}
func serveProd() error {
- log.Printf("running in production mode")
+ log.Printf("running in production mode.")
storageClient, err := storage.NewClient(context.Background())
if err != nil {
@@ -472,7 +491,7 @@
}
autocertManager := &autocert.Manager{
Prompt: autocert.AcceptTOS,
- HostPolicy: autocert.HostWhitelist("http2.golang.org"),
+ HostPolicy: autocert.HostWhitelist("http1.golang.org", "http2.golang.org"),
Cache: autocertcache.NewGoogleCloudStorageCache(storageClient, "golang-h2demo-autocert"),
}
diff --git a/http2/h2demo/launch.go b/http2/h2demo/launch.go
deleted file mode 100644
index df0866a..0000000
--- a/http2/h2demo/launch.go
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import (
- "bufio"
- "bytes"
- "encoding/json"
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net/http"
- "os"
- "strings"
- "time"
-
- "golang.org/x/oauth2"
- "golang.org/x/oauth2/google"
- compute "google.golang.org/api/compute/v1"
-)
-
-var (
- proj = flag.String("project", "symbolic-datum-552", "name of Project")
- zone = flag.String("zone", "us-central1-a", "GCE zone")
- mach = flag.String("machinetype", "n1-standard-1", "Machine type")
- instName = flag.String("instance_name", "http2-demo", "Name of VM instance.")
- sshPub = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
- staticIP = flag.String("static_ip", "130.211.116.44", "Static IP to use. If empty, automatic.")
-
- writeObject = flag.String("write_object", "", "If non-empty, a VM isn't created and the flag value is Google Cloud Storage bucket/object to write. The contents from stdin.")
- publicObject = flag.Bool("write_object_is_public", false, "Whether the object created by --write_object should be public.")
-)
-
-func readFile(v string) string {
- slurp, err := ioutil.ReadFile(v)
- if err != nil {
- log.Fatalf("Error reading %s: %v", v, err)
- }
- return strings.TrimSpace(string(slurp))
-}
-
-var config = &oauth2.Config{
- // The client-id and secret should be for an "Installed Application" when using
- // the CLI. Later we'll use a web application with a callback.
- ClientID: readFile("client-id.dat"),
- ClientSecret: readFile("client-secret.dat"),
- Endpoint: google.Endpoint,
- Scopes: []string{
- compute.DevstorageFullControlScope,
- compute.ComputeScope,
- "https://www.googleapis.com/auth/sqlservice",
- "https://www.googleapis.com/auth/sqlservice.admin",
- },
- RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
-}
-
-const baseConfig = `#cloud-config
-coreos:
- units:
- - name: h2demo.service
- command: start
- content: |
- [Unit]
- Description=HTTP2 Demo
-
- [Service]
- ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/h2demo http://storage.googleapis.com/http2-demo-server-tls/h2demo && chmod +x /opt/bin/h2demo'
- ExecStart=/opt/bin/h2demo --prod
- RestartSec=5s
- Restart=always
- Type=simple
-
- [Install]
- WantedBy=multi-user.target
-`
-
-func main() {
- flag.Parse()
- if *proj == "" {
- log.Fatalf("Missing --project flag")
- }
- prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
- machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
-
- const tokenFileName = "token.dat"
- tokenFile := tokenCacheFile(tokenFileName)
- tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
- token, err := tokenSource.Token()
- if err != nil {
- if *writeObject != "" {
- log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
- }
- log.Printf("Error getting token from %s: %v", tokenFileName, err)
- log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
- fmt.Print("\nEnter auth code: ")
- sc := bufio.NewScanner(os.Stdin)
- sc.Scan()
- authCode := strings.TrimSpace(sc.Text())
- token, err = config.Exchange(oauth2.NoContext, authCode)
- if err != nil {
- log.Fatalf("Error exchanging auth code for a token: %v", err)
- }
- if err := tokenFile.WriteToken(token); err != nil {
- log.Fatalf("Error writing to %s: %v", tokenFileName, err)
- }
- tokenSource = oauth2.ReuseTokenSource(token, nil)
- }
-
- oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
-
- if *writeObject != "" {
- writeCloudStorageObject(oauthClient)
- return
- }
-
- computeService, _ := compute.New(oauthClient)
-
- natIP := *staticIP
- if natIP == "" {
- // Try to find it by name.
- aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
- if err != nil {
- log.Fatal(err)
- }
- // http://godoc.org/code.google.com/p/google-api-go-client/compute/v1#AddressAggregatedList
- IPLoop:
- for _, asl := range aggAddrList.Items {
- for _, addr := range asl.Addresses {
- if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
- natIP = addr.Address
- break IPLoop
- }
- }
- }
- }
-
- cloudConfig := baseConfig
- if *sshPub != "" {
- key := strings.TrimSpace(readFile(*sshPub))
- cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", key)
- }
- if os.Getenv("USER") == "bradfitz" {
- cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
- }
- const maxCloudConfig = 32 << 10 // per compute API docs
- if len(cloudConfig) > maxCloudConfig {
- log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
- }
-
- instance := &compute.Instance{
- Name: *instName,
- Description: "Go Builder",
- MachineType: machType,
- Disks: []*compute.AttachedDisk{instanceDisk(computeService)},
- Tags: &compute.Tags{
- Items: []string{"http-server", "https-server"},
- },
- Metadata: &compute.Metadata{
- Items: []*compute.MetadataItems{
- {
- Key: "user-data",
- Value: &cloudConfig,
- },
- },
- },
- NetworkInterfaces: []*compute.NetworkInterface{
- {
- AccessConfigs: []*compute.AccessConfig{
- {
- Type: "ONE_TO_ONE_NAT",
- Name: "External NAT",
- NatIP: natIP,
- },
- },
- Network: prefix + "/global/networks/default",
- },
- },
- ServiceAccounts: []*compute.ServiceAccount{
- {
- Email: "default",
- Scopes: []string{
- compute.DevstorageFullControlScope,
- compute.ComputeScope,
- },
- },
- },
- }
-
- log.Printf("Creating instance...")
- op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
- if err != nil {
- log.Fatalf("Failed to create instance: %v", err)
- }
- opName := op.Name
- log.Printf("Created. Waiting on operation %v", opName)
-OpLoop:
- for {
- time.Sleep(2 * time.Second)
- op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
- if err != nil {
- log.Fatalf("Failed to get op %s: %v", opName, err)
- }
- switch op.Status {
- case "PENDING", "RUNNING":
- log.Printf("Waiting on operation %v", opName)
- continue
- case "DONE":
- if op.Error != nil {
- for _, operr := range op.Error.Errors {
- log.Printf("Error: %+v", operr)
- }
- log.Fatalf("Failed to start.")
- }
- log.Printf("Success. %+v", op)
- break OpLoop
- default:
- log.Fatalf("Unknown status %q: %+v", op.Status, op)
- }
- }
-
- inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
- if err != nil {
- log.Fatalf("Error getting instance after creation: %v", err)
- }
- ij, _ := json.MarshalIndent(inst, "", " ")
- log.Printf("Instance: %s", ij)
-}
-
-func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
- const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-stable-444-5-0-v20141016"
- diskName := *instName + "-disk"
-
- return &compute.AttachedDisk{
- AutoDelete: true,
- Boot: true,
- Type: "PERSISTENT",
- InitializeParams: &compute.AttachedDiskInitializeParams{
- DiskName: diskName,
- SourceImage: imageURL,
- DiskSizeGb: 50,
- },
- }
-}
-
-func writeCloudStorageObject(httpClient *http.Client) {
- content := os.Stdin
- const maxSlurp = 1 << 20
- var buf bytes.Buffer
- n, err := io.CopyN(&buf, content, maxSlurp)
- if err != nil && err != io.EOF {
- log.Fatalf("Error reading from stdin: %v, %v", n, err)
- }
- contentType := http.DetectContentType(buf.Bytes())
-
- req, err := http.NewRequest("PUT", "https://storage.googleapis.com/"+*writeObject, io.MultiReader(&buf, content))
- if err != nil {
- log.Fatal(err)
- }
- req.Header.Set("x-goog-api-version", "2")
- if *publicObject {
- req.Header.Set("x-goog-acl", "public-read")
- }
- req.Header.Set("Content-Type", contentType)
- res, err := httpClient.Do(req)
- if err != nil {
- log.Fatal(err)
- }
- if res.StatusCode != 200 {
- res.Write(os.Stderr)
- log.Fatalf("Failed.")
- }
- log.Printf("Success.")
- os.Exit(0)
-}
-
-type tokenCacheFile string
-
-func (f tokenCacheFile) Token() (*oauth2.Token, error) {
- slurp, err := ioutil.ReadFile(string(f))
- if err != nil {
- return nil, err
- }
- t := new(oauth2.Token)
- if err := json.Unmarshal(slurp, t); err != nil {
- return nil, err
- }
- return t, nil
-}
-
-func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
- jt, err := json.Marshal(t)
- if err != nil {
- return err
- }
- return ioutil.WriteFile(string(f), jt, 0600)
-}
diff --git a/http2/h2demo/tmpl.go b/http2/h2demo/tmpl.go
index 504d6a7..09fc729 100644
--- a/http2/h2demo/tmpl.go
+++ b/http2/h2demo/tmpl.go
@@ -43,7 +43,7 @@
<div style="padding:20px">
-<a href="https://{{.HTTPSHost}}/serverpush">HTTP/2 with Server Push</a> | <a href="http://{{.HTTPHost}}/serverpush">HTTP only</a>
+<a href="https://{{.HTTPSHost}}/serverpush">HTTP/2 with Server Push</a> | <a href="{{.HTTP1Prefix}}/serverpush">HTTP only</a>
<div id="loadtimes"></div>
</div>