vendor: revendor using glide-vc
This commit is contained in:
5
vendor/golang.org/x/net/http2/h2demo/.gitignore
generated
vendored
5
vendor/golang.org/x/net/http2/h2demo/.gitignore
generated
vendored
@@ -1,5 +0,0 @@
|
||||
h2demo
|
||||
h2demo.linux
|
||||
client-id.dat
|
||||
client-secret.dat
|
||||
token.dat
|
8
vendor/golang.org/x/net/http2/h2demo/Makefile
generated
vendored
8
vendor/golang.org/x/net/http2/h2demo/Makefile
generated
vendored
@@ -1,8 +0,0 @@
|
||||
h2demo.linux: h2demo.go
|
||||
GOOS=linux go build --tags=h2demo -o h2demo.linux .
|
||||
|
||||
FORCE:
|
||||
|
||||
upload: FORCE
|
||||
go install golang.org/x/build/cmd/upload
|
||||
upload --verbose --osarch=linux-amd64 --tags=h2demo --file=go:golang.org/x/net/http2/h2demo --public http2-demo-server-tls/h2demo
|
16
vendor/golang.org/x/net/http2/h2demo/README
generated
vendored
16
vendor/golang.org/x/net/http2/h2demo/README
generated
vendored
@@ -1,16 +0,0 @@
|
||||
|
||||
Client:
|
||||
-- Firefox nightly with about:config network.http.spdy.enabled.http2draft set true
|
||||
-- Chrome: go to chrome://flags/#enable-spdy4, save and restart (button at bottom)
|
||||
|
||||
Make CA:
|
||||
$ openssl genrsa -out rootCA.key 2048
|
||||
$ openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem
|
||||
... install that to Firefox
|
||||
|
||||
Make cert:
|
||||
$ openssl genrsa -out server.key 2048
|
||||
$ openssl req -new -key server.key -out server.csr
|
||||
$ openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500
|
||||
|
||||
|
504
vendor/golang.org/x/net/http2/h2demo/h2demo.go
generated
vendored
504
vendor/golang.org/x/net/http2/h2demo/h2demo.go
generated
vendored
@@ -1,504 +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 h2demo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"camlistore.org/pkg/googlestorage"
|
||||
"go4.org/syncutil/singleflight"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
var (
|
||||
prod = flag.Bool("prod", false, "Whether to configure itself to be the production http2.golang.org server.")
|
||||
|
||||
httpsAddr = flag.String("https_addr", "localhost:4430", "TLS address to listen on ('host:port' or ':port'). Required.")
|
||||
httpAddr = flag.String("http_addr", "", "Plain HTTP address to listen on ('host:port', or ':port'). Empty means no HTTP.")
|
||||
|
||||
hostHTTP = flag.String("http_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -http_addr.")
|
||||
hostHTTPS = flag.String("https_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -https_addr.")
|
||||
)
|
||||
|
||||
func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
io.WriteString(w, `<html>
|
||||
<body>
|
||||
<h1>Go + HTTP/2</h1>
|
||||
<p>Welcome to <a href="https://golang.org/">the Go language</a>'s <a href="https://http2.github.io/">HTTP/2</a> demo & interop server.</p>
|
||||
<p>Unfortunately, you're <b>not</b> using HTTP/2 right now. To do so:</p>
|
||||
<ul>
|
||||
<li>Use Firefox Nightly or go to <b>about:config</b> and enable "network.http.spdy.enabled.http2draft"</li>
|
||||
<li>Use Google Chrome Canary and/or go to <b>chrome://flags/#enable-spdy4</b> to <i>Enable SPDY/4</i> (Chrome's name for HTTP/2)</li>
|
||||
</ul>
|
||||
<p>See code & instructions for connecting at <a href="https://github.com/golang/net/tree/master/http2">https://github.com/golang/net/tree/master/http2</a>.</p>
|
||||
|
||||
</body></html>`)
|
||||
}
|
||||
|
||||
func home(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
io.WriteString(w, `<html>
|
||||
<body>
|
||||
<h1>Go + HTTP/2</h1>
|
||||
|
||||
<p>Welcome to <a href="https://golang.org/">the Go language</a>'s <a
|
||||
href="https://http2.github.io/">HTTP/2</a> demo & interop server.</p>
|
||||
|
||||
<p>Congratulations, <b>you're using HTTP/2 right now</b>.</p>
|
||||
|
||||
<p>This server exists for others in the HTTP/2 community to test their HTTP/2 client implementations and point out flaws in our server.</p>
|
||||
|
||||
<p>
|
||||
The code is at <a href="https://golang.org/x/net/http2">golang.org/x/net/http2</a> and
|
||||
is used transparently by the Go standard library from Go 1.6 and later.
|
||||
</p>
|
||||
|
||||
<p>Contact info: <i>bradfitz@golang.org</i>, or <a
|
||||
href="https://golang.org/s/http2bug">file a bug</a>.</p>
|
||||
|
||||
<h2>Handlers for testing</h2>
|
||||
<ul>
|
||||
<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="/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>
|
||||
<li>GET <a href="/goroutines">/goroutines</a> to see all active goroutines in this server</li>
|
||||
<li>PUT something to <a href="/crc32">/crc32</a> to get a count of number of bytes and its CRC-32</li>
|
||||
<li>PUT something to <a href="/ECHO">/ECHO</a> and it will be streamed back to you capitalized</li>
|
||||
</ul>
|
||||
|
||||
</body></html>`)
|
||||
}
|
||||
|
||||
func reqInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
fmt.Fprintf(w, "Method: %s\n", r.Method)
|
||||
fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
|
||||
fmt.Fprintf(w, "Host: %s\n", r.Host)
|
||||
fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr)
|
||||
fmt.Fprintf(w, "RequestURI: %q\n", r.RequestURI)
|
||||
fmt.Fprintf(w, "URL: %#v\n", r.URL)
|
||||
fmt.Fprintf(w, "Body.ContentLength: %d (-1 means unknown)\n", r.ContentLength)
|
||||
fmt.Fprintf(w, "Close: %v (relevant for HTTP/1 only)\n", r.Close)
|
||||
fmt.Fprintf(w, "TLS: %#v\n", r.TLS)
|
||||
fmt.Fprintf(w, "\nHeaders:\n")
|
||||
r.Header.Write(w)
|
||||
}
|
||||
|
||||
func crcHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "PUT" {
|
||||
http.Error(w, "PUT required.", 400)
|
||||
return
|
||||
}
|
||||
crc := crc32.NewIEEE()
|
||||
n, err := io.Copy(crc, r.Body)
|
||||
if err == nil {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
fmt.Fprintf(w, "bytes=%d, CRC32=%x", n, crc.Sum(nil))
|
||||
}
|
||||
}
|
||||
|
||||
type capitalizeReader struct {
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func (cr capitalizeReader) Read(p []byte) (n int, err error) {
|
||||
n, err = cr.r.Read(p)
|
||||
for i, b := range p[:n] {
|
||||
if b >= 'a' && b <= 'z' {
|
||||
p[i] = b - ('a' - 'A')
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type flushWriter struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (fw flushWriter) Write(p []byte) (n int, err error) {
|
||||
n, err = fw.w.Write(p)
|
||||
if f, ok := fw.w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "PUT" {
|
||||
http.Error(w, "PUT required.", 400)
|
||||
return
|
||||
}
|
||||
io.Copy(flushWriter{w}, capitalizeReader{r.Body})
|
||||
}
|
||||
|
||||
var (
|
||||
fsGrp singleflight.Group
|
||||
fsMu sync.Mutex // guards fsCache
|
||||
fsCache = map[string]http.Handler{}
|
||||
)
|
||||
|
||||
// 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 {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
hi, err := fsGrp.Do(url, func() (interface{}, error) {
|
||||
fsMu.Lock()
|
||||
if h, ok := fsCache[url]; ok {
|
||||
fsMu.Unlock()
|
||||
return h, nil
|
||||
}
|
||||
fsMu.Unlock()
|
||||
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
slurp, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
modTime := time.Now()
|
||||
var h http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeContent(w, r, path.Base(url), modTime, bytes.NewReader(slurp))
|
||||
})
|
||||
fsMu.Lock()
|
||||
fsCache[url] = h
|
||||
fsMu.Unlock()
|
||||
return h, nil
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
hi.(http.Handler).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func clockStreamHandler(w http.ResponseWriter, r *http.Request) {
|
||||
clientGone := w.(http.CloseNotifier).CloseNotify()
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
defer ticker.Stop()
|
||||
fmt.Fprintf(w, "# ~1KB of junk to force browsers to start rendering immediately: \n")
|
||||
io.WriteString(w, strings.Repeat("# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", 13))
|
||||
|
||||
for {
|
||||
fmt.Fprintf(w, "%v\n", time.Now())
|
||||
w.(http.Flusher).Flush()
|
||||
select {
|
||||
case <-ticker.C:
|
||||
case <-clientGone:
|
||||
log.Printf("Client %v disconnected from the clock", r.RemoteAddr)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func registerHandlers() {
|
||||
tiles := newGopherTilesHandler()
|
||||
|
||||
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
|
||||
}
|
||||
http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
if r.ProtoMajor == 1 {
|
||||
if r.URL.Path == "/reqinfo" {
|
||||
reqInfoHandler(w, r)
|
||||
return
|
||||
}
|
||||
homeOldHTTP(w, r)
|
||||
return
|
||||
}
|
||||
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.HandleFunc("/reqinfo", reqInfoHandler)
|
||||
mux2.HandleFunc("/crc32", crcHandler)
|
||||
mux2.HandleFunc("/ECHO", echoCapitalHandler)
|
||||
mux2.HandleFunc("/clockstream", clockStreamHandler)
|
||||
mux2.Handle("/gophertiles", tiles)
|
||||
mux2.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
})
|
||||
stripHomedir := regexp.MustCompile(`/(Users|home)/\w+`)
|
||||
mux2.HandleFunc("/goroutines", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
buf := make([]byte, 2<<20)
|
||||
w.Write(stripHomedir.ReplaceAll(buf[:runtime.Stack(buf, true)], nil))
|
||||
})
|
||||
}
|
||||
|
||||
func newGopherTilesHandler() http.Handler {
|
||||
const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg"
|
||||
res, err := http.Get(gopherURL)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
log.Fatalf("Error fetching %s: %v", gopherURL, res.Status)
|
||||
}
|
||||
slurp, err := ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
im, err := jpeg.Decode(bytes.NewReader(slurp))
|
||||
if err != nil {
|
||||
if len(slurp) > 1024 {
|
||||
slurp = slurp[:1024]
|
||||
}
|
||||
log.Fatalf("Failed to decode gopher image: %v (got %q)", err, slurp)
|
||||
}
|
||||
|
||||
type subImager interface {
|
||||
SubImage(image.Rectangle) image.Image
|
||||
}
|
||||
const tileSize = 32
|
||||
xt := im.Bounds().Max.X / tileSize
|
||||
yt := im.Bounds().Max.Y / tileSize
|
||||
var tile [][][]byte // y -> x -> jpeg bytes
|
||||
for yi := 0; yi < yt; yi++ {
|
||||
var row [][]byte
|
||||
for xi := 0; xi < xt; xi++ {
|
||||
si := im.(subImager).SubImage(image.Rectangle{
|
||||
Min: image.Point{xi * tileSize, yi * tileSize},
|
||||
Max: image.Point{(xi + 1) * tileSize, (yi + 1) * tileSize},
|
||||
})
|
||||
buf := new(bytes.Buffer)
|
||||
if err := jpeg.Encode(buf, si, &jpeg.Options{Quality: 90}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
row = append(row, buf.Bytes())
|
||||
}
|
||||
tile = append(tile, row)
|
||||
}
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ms, _ := strconv.Atoi(r.FormValue("latency"))
|
||||
const nanosPerMilli = 1e6
|
||||
if r.FormValue("x") != "" {
|
||||
x, _ := strconv.Atoi(r.FormValue("x"))
|
||||
y, _ := strconv.Atoi(r.FormValue("y"))
|
||||
if ms <= 1000 {
|
||||
time.Sleep(time.Duration(ms) * nanosPerMilli)
|
||||
}
|
||||
if x >= 0 && x < xt && y >= 0 && y < yt {
|
||||
http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(tile[y][x]))
|
||||
return
|
||||
}
|
||||
}
|
||||
io.WriteString(w, "<html><body onload='showtimes()'>")
|
||||
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",
|
||||
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'>",
|
||||
tileSize, tileSize, x, y, cacheBust, ms)
|
||||
}
|
||||
io.WriteString(w, "<br/>\n")
|
||||
}
|
||||
io.WriteString(w, `<p><div id='loadtimes'></div></p>
|
||||
<script>
|
||||
function showtimes() {
|
||||
var times = 'Times from connection start:<br>'
|
||||
times += 'DOM loaded: ' + (window.performance.timing.domContentLoadedEventEnd - window.performance.timing.connectStart) + 'ms<br>'
|
||||
times += 'DOM complete (images loaded): ' + (window.performance.timing.domComplete - window.performance.timing.connectStart) + 'ms<br>'
|
||||
document.getElementById('loadtimes').innerHTML = times
|
||||
}
|
||||
</script>
|
||||
<hr><a href='/'><< Back to Go HTTP/2 demo server</a></body></html>`)
|
||||
})
|
||||
}
|
||||
|
||||
func httpsHost() string {
|
||||
if *hostHTTPS != "" {
|
||||
return *hostHTTPS
|
||||
}
|
||||
if v := *httpsAddr; strings.HasPrefix(v, ":") {
|
||||
return "localhost" + v
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func httpHost() string {
|
||||
if *hostHTTP != "" {
|
||||
return *hostHTTP
|
||||
}
|
||||
if v := *httpAddr; strings.HasPrefix(v, ":") {
|
||||
return "localhost" + v
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func serveProdTLS() error {
|
||||
c, err := googlestorage.NewServiceClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slurp := func(key string) ([]byte, error) {
|
||||
const bucket = "http2-demo-server-tls"
|
||||
rc, _, err := c.GetObject(&googlestorage.Object{
|
||||
Bucket: bucket,
|
||||
Key: key,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error fetching GCS object %q in bucket %q: %v", key, bucket, err)
|
||||
}
|
||||
defer rc.Close()
|
||||
return ioutil.ReadAll(rc)
|
||||
}
|
||||
certPem, err := slurp("http2.golang.org.chained.pem")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPem, err := slurp("http2.golang.org.key")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cert, err := tls.X509KeyPair(certPem, keyPem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv := &http.Server{
|
||||
TLSConfig: &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
},
|
||||
}
|
||||
http2.ConfigureServer(srv, &http2.Server{})
|
||||
ln, err := net.Listen("tcp", ":443")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig))
|
||||
}
|
||||
|
||||
type tcpKeepAliveListener struct {
|
||||
*net.TCPListener
|
||||
}
|
||||
|
||||
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
||||
tc, err := ln.AcceptTCP()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tc.SetKeepAlive(true)
|
||||
tc.SetKeepAlivePeriod(3 * time.Minute)
|
||||
return tc, nil
|
||||
}
|
||||
|
||||
func serveProd() error {
|
||||
errc := make(chan error, 2)
|
||||
go func() { errc <- http.ListenAndServe(":80", nil) }()
|
||||
go func() { errc <- serveProdTLS() }()
|
||||
return <-errc
|
||||
}
|
||||
|
||||
const idleTimeout = 5 * time.Minute
|
||||
const activeTimeout = 10 * time.Minute
|
||||
|
||||
// TODO: put this into the standard library and actually send
|
||||
// PING frames and GOAWAY, etc: golang.org/issue/14204
|
||||
func idleTimeoutHook() func(net.Conn, http.ConnState) {
|
||||
var mu sync.Mutex
|
||||
m := map[net.Conn]*time.Timer{}
|
||||
return func(c net.Conn, cs http.ConnState) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if t, ok := m[c]; ok {
|
||||
delete(m, c)
|
||||
t.Stop()
|
||||
}
|
||||
var d time.Duration
|
||||
switch cs {
|
||||
case http.StateNew, http.StateIdle:
|
||||
d = idleTimeout
|
||||
case http.StateActive:
|
||||
d = activeTimeout
|
||||
default:
|
||||
return
|
||||
}
|
||||
m[c] = time.AfterFunc(d, func() {
|
||||
log.Printf("closing idle conn %v after %v", c.RemoteAddr(), d)
|
||||
go c.Close()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var srv http.Server
|
||||
flag.BoolVar(&http2.VerboseLogs, "verbose", false, "Verbose HTTP/2 debugging.")
|
||||
flag.Parse()
|
||||
srv.Addr = *httpsAddr
|
||||
srv.ConnState = idleTimeoutHook()
|
||||
|
||||
registerHandlers()
|
||||
|
||||
if *prod {
|
||||
*hostHTTP = "http2.golang.org"
|
||||
*hostHTTPS = "http2.golang.org"
|
||||
log.Fatal(serveProd())
|
||||
}
|
||||
|
||||
url := "https://" + httpsHost() + "/"
|
||||
log.Printf("Listening on " + url)
|
||||
http2.ConfigureServer(&srv, &http2.Server{})
|
||||
|
||||
if *httpAddr != "" {
|
||||
go func() {
|
||||
log.Printf("Listening on http://" + httpHost() + "/ (for unencrypted HTTP/1)")
|
||||
log.Fatal(http.ListenAndServe(*httpAddr, nil))
|
||||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
|
||||
}()
|
||||
select {}
|
||||
}
|
302
vendor/golang.org/x/net/http2/h2demo/launch.go
generated
vendored
302
vendor/golang.org/x/net/http2/h2demo/launch.go
generated
vendored
@@ -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)
|
||||
}
|
27
vendor/golang.org/x/net/http2/h2demo/rootCA.key
generated
vendored
27
vendor/golang.org/x/net/http2/h2demo/rootCA.key
generated
vendored
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAt5fAjp4fTcekWUTfzsp0kyih1OYbsGL0KX1eRbSSR8Od0+9Q
|
||||
62Hyny+GFwMTb4A/KU8mssoHvcceSAAbwfbxFK/+s51TobqUnORZrOoTZjkUygby
|
||||
XDSK99YBbcR1Pip8vwMTm4XKuLtCigeBBdjjAQdgUO28LENGlsMnmeYkJfODVGnV
|
||||
mr5Ltb9ANA8IKyTfsnHJ4iOCS/PlPbUj2q7YnoVLposUBMlgUb/CykX3mOoLb4yJ
|
||||
JQyA/iST6ZxiIEj36D4yWZ5lg7YJl+UiiBQHGCnPdGyipqV06ex0heYWcaiW8LWZ
|
||||
SUQ93jQ+WVCH8hT7DQO1dmsvUmXlq/JeAlwQ/QIDAQABAoIBAFFHV7JMAqPWnMYA
|
||||
nezY6J81v9+XN+7xABNWM2Q8uv4WdksbigGLTXR3/680Z2hXqJ7LMeC5XJACFT/e
|
||||
/Gr0vmpgOCygnCPfjGehGKpavtfksXV3edikUlnCXsOP1C//c1bFL+sMYmFCVgTx
|
||||
qYdDK8yKzXNGrKYT6q5YG7IglyRNV1rsQa8lM/5taFYiD1Ck/3tQi3YIq8Lcuser
|
||||
hrxsMABcQ6mi+EIvG6Xr4mfJug0dGJMHG4RG1UGFQn6RXrQq2+q53fC8ZbVUSi0j
|
||||
NQ918aKFzktwv+DouKU0ME4I9toks03gM860bAL7zCbKGmwR3hfgX/TqzVCWpG9E
|
||||
LDVfvekCgYEA8fk9N53jbBRmULUGEf4qWypcLGiZnNU0OeXWpbPV9aa3H0VDytA7
|
||||
8fCN2dPAVDPqlthMDdVe983NCNwp2Yo8ZimDgowyIAKhdC25s1kejuaiH9OAPj3c
|
||||
0f8KbriYX4n8zNHxFwK6Ae3pQ6EqOLJVCUsziUaZX9nyKY5aZlyX6xcCgYEAwjws
|
||||
K62PjC64U5wYddNLp+kNdJ4edx+a7qBb3mEgPvSFT2RO3/xafJyG8kQB30Mfstjd
|
||||
bRxyUV6N0vtX1zA7VQtRUAvfGCecpMo+VQZzcHXKzoRTnQ7eZg4Lmj5fQ9tOAKAo
|
||||
QCVBoSW/DI4PZL26CAMDcAba4Pa22ooLapoRIQsCgYA6pIfkkbxLNkpxpt2YwLtt
|
||||
Kr/590O7UaR9n6k8sW/aQBRDXNsILR1KDl2ifAIxpf9lnXgZJiwE7HiTfCAcW7c1
|
||||
nzwDCI0hWuHcMTS/NYsFYPnLsstyyjVZI3FY0h4DkYKV9Q9z3zJLQ2hz/nwoD3gy
|
||||
b2pHC7giFcTts1VPV4Nt8wKBgHeFn4ihHJweg76vZz3Z78w7VNRWGFklUalVdDK7
|
||||
gaQ7w2y/ROn/146mo0OhJaXFIFRlrpvdzVrU3GDf2YXJYDlM5ZRkObwbZADjksev
|
||||
WInzcgDy3KDg7WnPasRXbTfMU4t/AkW2p1QKbi3DnSVYuokDkbH2Beo45vxDxhKr
|
||||
C69RAoGBAIyo3+OJenoZmoNzNJl2WPW5MeBUzSh8T/bgyjFTdqFHF5WiYRD/lfHj
|
||||
x9Glyw2nutuT4hlOqHvKhgTYdDMsF2oQ72fe3v8Q5FU7FuKndNPEAyvKNXZaShVA
|
||||
hnlhv5DjXKb0wFWnt5PCCiQLtzG0yyHaITrrEme7FikkIcTxaX/Y
|
||||
-----END RSA PRIVATE KEY-----
|
26
vendor/golang.org/x/net/http2/h2demo/rootCA.pem
generated
vendored
26
vendor/golang.org/x/net/http2/h2demo/rootCA.pem
generated
vendored
@@ -1,26 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEWjCCA0KgAwIBAgIJALfRlWsI8YQHMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEUMBIG
|
||||
A1UEChMLQnJhZGZpdHppbmMxEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsGCSqGSIb3
|
||||
DQEJARYOYnJhZEBkYW5nYS5jb20wHhcNMTQwNzE1MjA0NjA1WhcNMTcwNTA0MjA0
|
||||
NjA1WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBG
|
||||
cmFuY2lzY28xFDASBgNVBAoTC0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhv
|
||||
c3QxHTAbBgkqhkiG9w0BCQEWDmJyYWRAZGFuZ2EuY29tMIIBIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAQ8AMIIBCgKCAQEAt5fAjp4fTcekWUTfzsp0kyih1OYbsGL0KX1eRbSS
|
||||
R8Od0+9Q62Hyny+GFwMTb4A/KU8mssoHvcceSAAbwfbxFK/+s51TobqUnORZrOoT
|
||||
ZjkUygbyXDSK99YBbcR1Pip8vwMTm4XKuLtCigeBBdjjAQdgUO28LENGlsMnmeYk
|
||||
JfODVGnVmr5Ltb9ANA8IKyTfsnHJ4iOCS/PlPbUj2q7YnoVLposUBMlgUb/CykX3
|
||||
mOoLb4yJJQyA/iST6ZxiIEj36D4yWZ5lg7YJl+UiiBQHGCnPdGyipqV06ex0heYW
|
||||
caiW8LWZSUQ93jQ+WVCH8hT7DQO1dmsvUmXlq/JeAlwQ/QIDAQABo4HgMIHdMB0G
|
||||
A1UdDgQWBBRcAROthS4P4U7vTfjByC569R7E6DCBrQYDVR0jBIGlMIGigBRcAROt
|
||||
hS4P4U7vTfjByC569R7E6KF/pH0wezELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB
|
||||
MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKEwtCcmFkZml0emluYzES
|
||||
MBAGA1UEAxMJbG9jYWxob3N0MR0wGwYJKoZIhvcNAQkBFg5icmFkQGRhbmdhLmNv
|
||||
bYIJALfRlWsI8YQHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAG6h
|
||||
U9f9sNH0/6oBbGGy2EVU0UgITUQIrFWo9rFkrW5k/XkDjQm+3lzjT0iGR4IxE/Ao
|
||||
eU6sQhua7wrWeFEn47GL98lnCsJdD7oZNhFmQ95Tb/LnDUjs5Yj9brP0NWzXfYU4
|
||||
UK2ZnINJRcJpB8iRCaCxE8DdcUF0XqIEq6pA272snoLmiXLMvNl3kYEdm+je6voD
|
||||
58SNVEUsztzQyXmJEhCpwVI0A6QCjzXj+qvpmw3ZZHi8JwXei8ZZBLTSFBki8Z7n
|
||||
sH9BBH38/SzUmAN4QHSPy1gjqm00OAE8NaYDkh/bzE4d7mLGGMWp/WE3KPSu82HF
|
||||
kPe6XoSbiLm/kxk32T0=
|
||||
-----END CERTIFICATE-----
|
1
vendor/golang.org/x/net/http2/h2demo/rootCA.srl
generated
vendored
1
vendor/golang.org/x/net/http2/h2demo/rootCA.srl
generated
vendored
@@ -1 +0,0 @@
|
||||
E2CE26BF3285059C
|
20
vendor/golang.org/x/net/http2/h2demo/server.crt
generated
vendored
20
vendor/golang.org/x/net/http2/h2demo/server.crt
generated
vendored
@@ -1,20 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPjCCAiYCCQDizia/MoUFnDANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNVBAoT
|
||||
C0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhvc3QxHTAbBgkqhkiG9w0BCQEW
|
||||
DmJyYWRAZGFuZ2EuY29tMB4XDTE0MDcxNTIwNTAyN1oXDTE1MTEyNzIwNTAyN1ow
|
||||
RzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJTRjEeMBwGA1UE
|
||||
ChMVYnJhZGZpdHogaHR0cDIgc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDifx2l
|
||||
gZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1LmJ4c2
|
||||
dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nefb3HL
|
||||
A7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55mjws
|
||||
/vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/fz88
|
||||
F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABMA0GCSqGSIb3DQEBBQUAA4IB
|
||||
AQC0zL+n/YpRZOdulSu9tS8FxrstXqGWoxfe+vIUgqfMZ5+0MkjJ/vW0FqlLDl2R
|
||||
rn4XaR3e7FmWkwdDVbq/UB6lPmoAaFkCgh9/5oapMaclNVNnfF3fjCJfRr+qj/iD
|
||||
EmJStTIN0ZuUjAlpiACmfnpEU55PafT5Zx+i1yE4FGjw8bJpFoyD4Hnm54nGjX19
|
||||
KeCuvcYFUPnBm3lcL0FalF2AjqV02WTHYNQk7YF/oeO7NKBoEgvGvKG3x+xaOeBI
|
||||
dwvdq175ZsGul30h+QjrRlXhH/twcuaT3GSdoysDl9cCYE8f1Mk8PD6gan3uBCJU
|
||||
90p6/CbU71bGbfpM2PHot2fm
|
||||
-----END CERTIFICATE-----
|
27
vendor/golang.org/x/net/http2/h2demo/server.key
generated
vendored
27
vendor/golang.org/x/net/http2/h2demo/server.key
generated
vendored
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDi
|
||||
fx2lgZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1Lm
|
||||
J4c2dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nef
|
||||
b3HLA7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55
|
||||
mjws/vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/
|
||||
fz88F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABAoIBADQ2spUwbY+bcz4p
|
||||
3M66ECrNQTBggP40gYl2XyHxGGOu2xhZ94f9ELf1hjRWU2DUKWco1rJcdZClV6q3
|
||||
qwmXvcM2Q/SMS8JW0ImkNVl/0/NqPxGatEnj8zY30d/L8hGFb0orzFu/XYA5gCP4
|
||||
NbN2WrXgk3ZLeqwcNxHHtSiJWGJ/fPyeDWAu/apy75u9Xf2GlzBZmV6HYD9EfK80
|
||||
LTlI60f5FO487CrJnboL7ovPJrIHn+k05xRQqwma4orpz932rTXnTjs9Lg6KtbQN
|
||||
a7PrqfAntIISgr11a66Mng3IYH1lYqJsWJJwX/xHT4WLEy0EH4/0+PfYemJekz2+
|
||||
Co62drECgYEA6O9zVJZXrLSDsIi54cfxA7nEZWm5CAtkYWeAHa4EJ+IlZ7gIf9sL
|
||||
W8oFcEfFGpvwVqWZ+AsQ70dsjXAv3zXaG0tmg9FtqWp7pzRSMPidifZcQwWkKeTO
|
||||
gJnFmnVyed8h6GfjTEu4gxo1/S5U0V+mYSha01z5NTnN6ltKx1Or3b0CgYEAxRgm
|
||||
S30nZxnyg/V7ys61AZhst1DG2tkZXEMcA7dYhabMoXPJAP/EfhlWwpWYYUs/u0gS
|
||||
Wwmf5IivX5TlYScgmkvb/NYz0u4ZmOXkLTnLPtdKKFXhjXJcHjUP67jYmOxNlJLp
|
||||
V4vLRnFxTpffAV+OszzRxsXX6fvruwZBANYJeXUCgYBVouLFsFgfWGYp2rpr9XP4
|
||||
KK25kvrBqF6JKOIDB1zjxNJ3pUMKrl8oqccCFoCyXa4oTM2kUX0yWxHfleUjrMq4
|
||||
yimwQKiOZmV7fVLSSjSw6e/VfBd0h3gb82ygcplZkN0IclkwTY5SNKqwn/3y07V5
|
||||
drqdhkrgdJXtmQ6O5YYECQKBgATERcDToQ1USlI4sKrB/wyv1AlG8dg/IebiVJ4e
|
||||
ZAyvcQmClFzq0qS+FiQUnB/WQw9TeeYrwGs1hxBHuJh16srwhLyDrbMvQP06qh8R
|
||||
48F8UXXSRec22dV9MQphaROhu2qZdv1AC0WD3tqov6L33aqmEOi+xi8JgbT/PLk5
|
||||
c/c1AoGBAI1A/02ryksW6/wc7/6SP2M2rTy4m1sD/GnrTc67EHnRcVBdKO6qH2RY
|
||||
nqC8YcveC2ZghgPTDsA3VGuzuBXpwY6wTyV99q6jxQJ6/xcrD9/NUG6Uwv/xfCxl
|
||||
IJLeBYEqQundSSny3VtaAUK8Ul1nxpTvVRNwtcyWTo8RHAAyNPWd
|
||||
-----END RSA PRIVATE KEY-----
|
97
vendor/golang.org/x/net/http2/h2i/README.md
generated
vendored
97
vendor/golang.org/x/net/http2/h2i/README.md
generated
vendored
@@ -1,97 +0,0 @@
|
||||
# h2i
|
||||
|
||||
**h2i** is an interactive HTTP/2 ("h2") console debugger. Miss the good ol'
|
||||
days of telnetting to your HTTP/1.n servers? We're bringing you
|
||||
back.
|
||||
|
||||
Features:
|
||||
- send raw HTTP/2 frames
|
||||
- PING
|
||||
- SETTINGS
|
||||
- HEADERS
|
||||
- etc
|
||||
- type in HTTP/1.n and have it auto-HPACK/frame-ify it for HTTP/2
|
||||
- pretty print all received HTTP/2 frames from the peer (including HPACK decoding)
|
||||
- tab completion of commands, options
|
||||
|
||||
Not yet features, but soon:
|
||||
- unnecessary CONTINUATION frames on short boundaries, to test peer implementations
|
||||
- request bodies (DATA frames)
|
||||
- send invalid frames for testing server implementations (supported by underlying Framer)
|
||||
|
||||
Later:
|
||||
- act like a server
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go get golang.org/x/net/http2/h2i
|
||||
$ h2i <host>
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
```
|
||||
$ h2i
|
||||
Usage: h2i <hostname>
|
||||
|
||||
-insecure
|
||||
Whether to skip TLS cert validation
|
||||
-nextproto string
|
||||
Comma-separated list of NPN/ALPN protocol names to negotiate. (default "h2,h2-14")
|
||||
|
||||
$ h2i google.com
|
||||
Connecting to google.com:443 ...
|
||||
Connected to 74.125.224.41:443
|
||||
Negotiated protocol "h2-14"
|
||||
[FrameHeader SETTINGS len=18]
|
||||
[MAX_CONCURRENT_STREAMS = 100]
|
||||
[INITIAL_WINDOW_SIZE = 1048576]
|
||||
[MAX_FRAME_SIZE = 16384]
|
||||
[FrameHeader WINDOW_UPDATE len=4]
|
||||
Window-Increment = 983041
|
||||
|
||||
h2i> PING h2iSayHI
|
||||
[FrameHeader PING flags=ACK len=8]
|
||||
Data = "h2iSayHI"
|
||||
h2i> headers
|
||||
(as HTTP/1.1)> GET / HTTP/1.1
|
||||
(as HTTP/1.1)> Host: ip.appspot.com
|
||||
(as HTTP/1.1)> User-Agent: h2i/brad-n-blake
|
||||
(as HTTP/1.1)>
|
||||
Opening Stream-ID 1:
|
||||
:authority = ip.appspot.com
|
||||
:method = GET
|
||||
:path = /
|
||||
:scheme = https
|
||||
user-agent = h2i/brad-n-blake
|
||||
[FrameHeader HEADERS flags=END_HEADERS stream=1 len=77]
|
||||
:status = "200"
|
||||
alternate-protocol = "443:quic,p=1"
|
||||
content-length = "15"
|
||||
content-type = "text/html"
|
||||
date = "Fri, 01 May 2015 23:06:56 GMT"
|
||||
server = "Google Frontend"
|
||||
[FrameHeader DATA flags=END_STREAM stream=1 len=15]
|
||||
"173.164.155.78\n"
|
||||
[FrameHeader PING len=8]
|
||||
Data = "\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
h2i> ping
|
||||
[FrameHeader PING flags=ACK len=8]
|
||||
Data = "h2i_ping"
|
||||
h2i> ping
|
||||
[FrameHeader PING flags=ACK len=8]
|
||||
Data = "h2i_ping"
|
||||
h2i> ping
|
||||
[FrameHeader GOAWAY len=22]
|
||||
Last-Stream-ID = 1; Error-Code = PROTOCOL_ERROR (1)
|
||||
|
||||
ReadFrame: EOF
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
Quick few hour hack. So much yet to do. Feel free to file issues for
|
||||
bugs or wishlist items, but [@bmizerany](https://github.com/bmizerany/)
|
||||
and I aren't yet accepting pull requests until things settle down.
|
||||
|
501
vendor/golang.org/x/net/http2/h2i/h2i.go
generated
vendored
501
vendor/golang.org/x/net/http2/h2i/h2i.go
generated
vendored
@@ -1,501 +0,0 @@
|
||||
// Copyright 2015 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 !plan9,!solaris
|
||||
|
||||
/*
|
||||
The h2i command is an interactive HTTP/2 console.
|
||||
|
||||
Usage:
|
||||
$ h2i [flags] <hostname>
|
||||
|
||||
Interactive commands in the console: (all parts case-insensitive)
|
||||
|
||||
ping [data]
|
||||
settings ack
|
||||
settings FOO=n BAR=z
|
||||
headers (open a new stream by typing HTTP/1.1)
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
// Flags
|
||||
var (
|
||||
flagNextProto = flag.String("nextproto", "h2,h2-14", "Comma-separated list of NPN/ALPN protocol names to negotiate.")
|
||||
flagInsecure = flag.Bool("insecure", false, "Whether to skip TLS cert validation")
|
||||
flagSettings = flag.String("settings", "empty", "comma-separated list of KEY=value settings for the initial SETTINGS frame. The magic value 'empty' sends an empty initial settings frame, and the magic value 'omit' causes no initial settings frame to be sent.")
|
||||
)
|
||||
|
||||
type command struct {
|
||||
run func(*h2i, []string) error // required
|
||||
|
||||
// complete optionally specifies tokens (case-insensitive) which are
|
||||
// valid for this subcommand.
|
||||
complete func() []string
|
||||
}
|
||||
|
||||
var commands = map[string]command{
|
||||
"ping": {run: (*h2i).cmdPing},
|
||||
"settings": {
|
||||
run: (*h2i).cmdSettings,
|
||||
complete: func() []string {
|
||||
return []string{
|
||||
"ACK",
|
||||
http2.SettingHeaderTableSize.String(),
|
||||
http2.SettingEnablePush.String(),
|
||||
http2.SettingMaxConcurrentStreams.String(),
|
||||
http2.SettingInitialWindowSize.String(),
|
||||
http2.SettingMaxFrameSize.String(),
|
||||
http2.SettingMaxHeaderListSize.String(),
|
||||
}
|
||||
},
|
||||
},
|
||||
"quit": {run: (*h2i).cmdQuit},
|
||||
"headers": {run: (*h2i).cmdHeaders},
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: h2i <hostname>\n\n")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
// withPort adds ":443" if another port isn't already present.
|
||||
func withPort(host string) string {
|
||||
if _, _, err := net.SplitHostPort(host); err != nil {
|
||||
return net.JoinHostPort(host, "443")
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
// h2i is the app's state.
|
||||
type h2i struct {
|
||||
host string
|
||||
tc *tls.Conn
|
||||
framer *http2.Framer
|
||||
term *terminal.Terminal
|
||||
|
||||
// owned by the command loop:
|
||||
streamID uint32
|
||||
hbuf bytes.Buffer
|
||||
henc *hpack.Encoder
|
||||
|
||||
// owned by the readFrames loop:
|
||||
peerSetting map[http2.SettingID]uint32
|
||||
hdec *hpack.Decoder
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
log.SetFlags(0)
|
||||
|
||||
host := flag.Arg(0)
|
||||
app := &h2i{
|
||||
host: host,
|
||||
peerSetting: make(map[http2.SettingID]uint32),
|
||||
}
|
||||
app.henc = hpack.NewEncoder(&app.hbuf)
|
||||
|
||||
if err := app.Main(); err != nil {
|
||||
if app.term != nil {
|
||||
app.logf("%v\n", err)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "\n")
|
||||
}
|
||||
|
||||
func (app *h2i) Main() error {
|
||||
cfg := &tls.Config{
|
||||
ServerName: app.host,
|
||||
NextProtos: strings.Split(*flagNextProto, ","),
|
||||
InsecureSkipVerify: *flagInsecure,
|
||||
}
|
||||
|
||||
hostAndPort := withPort(app.host)
|
||||
log.Printf("Connecting to %s ...", hostAndPort)
|
||||
tc, err := tls.Dial("tcp", hostAndPort, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error dialing %s: %v", withPort(app.host), err)
|
||||
}
|
||||
log.Printf("Connected to %v", tc.RemoteAddr())
|
||||
defer tc.Close()
|
||||
|
||||
if err := tc.Handshake(); err != nil {
|
||||
return fmt.Errorf("TLS handshake: %v", err)
|
||||
}
|
||||
if !*flagInsecure {
|
||||
if err := tc.VerifyHostname(app.host); err != nil {
|
||||
return fmt.Errorf("VerifyHostname: %v", err)
|
||||
}
|
||||
}
|
||||
state := tc.ConnectionState()
|
||||
log.Printf("Negotiated protocol %q", state.NegotiatedProtocol)
|
||||
if !state.NegotiatedProtocolIsMutual || state.NegotiatedProtocol == "" {
|
||||
return fmt.Errorf("Could not negotiate protocol mutually")
|
||||
}
|
||||
|
||||
if _, err := io.WriteString(tc, http2.ClientPreface); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app.framer = http2.NewFramer(tc, tc)
|
||||
|
||||
oldState, err := terminal.MakeRaw(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer terminal.Restore(0, oldState)
|
||||
|
||||
var screen = struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
}{os.Stdin, os.Stdout}
|
||||
|
||||
app.term = terminal.NewTerminal(screen, "h2i> ")
|
||||
lastWord := regexp.MustCompile(`.+\W(\w+)$`)
|
||||
app.term.AutoCompleteCallback = func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
|
||||
if key != '\t' {
|
||||
return
|
||||
}
|
||||
if pos != len(line) {
|
||||
// TODO: we're being lazy for now, only supporting tab completion at the end.
|
||||
return
|
||||
}
|
||||
// Auto-complete for the command itself.
|
||||
if !strings.Contains(line, " ") {
|
||||
var name string
|
||||
name, _, ok = lookupCommand(line)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
return name, len(name), true
|
||||
}
|
||||
_, c, ok := lookupCommand(line[:strings.IndexByte(line, ' ')])
|
||||
if !ok || c.complete == nil {
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(line, " ") {
|
||||
app.logf("%s", strings.Join(c.complete(), " "))
|
||||
return line, pos, true
|
||||
}
|
||||
m := lastWord.FindStringSubmatch(line)
|
||||
if m == nil {
|
||||
return line, len(line), true
|
||||
}
|
||||
soFar := m[1]
|
||||
var match []string
|
||||
for _, cand := range c.complete() {
|
||||
if len(soFar) > len(cand) || !strings.EqualFold(cand[:len(soFar)], soFar) {
|
||||
continue
|
||||
}
|
||||
match = append(match, cand)
|
||||
}
|
||||
if len(match) == 0 {
|
||||
return
|
||||
}
|
||||
if len(match) > 1 {
|
||||
// TODO: auto-complete any common prefix
|
||||
app.logf("%s", strings.Join(match, " "))
|
||||
return line, pos, true
|
||||
}
|
||||
newLine = line[:len(line)-len(soFar)] + match[0]
|
||||
return newLine, len(newLine), true
|
||||
|
||||
}
|
||||
|
||||
errc := make(chan error, 2)
|
||||
go func() { errc <- app.readFrames() }()
|
||||
go func() { errc <- app.readConsole() }()
|
||||
return <-errc
|
||||
}
|
||||
|
||||
func (app *h2i) logf(format string, args ...interface{}) {
|
||||
fmt.Fprintf(app.term, format+"\n", args...)
|
||||
}
|
||||
|
||||
func (app *h2i) readConsole() error {
|
||||
if s := *flagSettings; s != "omit" {
|
||||
var args []string
|
||||
if s != "empty" {
|
||||
args = strings.Split(s, ",")
|
||||
}
|
||||
_, c, ok := lookupCommand("settings")
|
||||
if !ok {
|
||||
panic("settings command not found")
|
||||
}
|
||||
c.run(app, args)
|
||||
}
|
||||
|
||||
for {
|
||||
line, err := app.term.ReadLine()
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("terminal.ReadLine: %v", err)
|
||||
}
|
||||
f := strings.Fields(line)
|
||||
if len(f) == 0 {
|
||||
continue
|
||||
}
|
||||
cmd, args := f[0], f[1:]
|
||||
if _, c, ok := lookupCommand(cmd); ok {
|
||||
err = c.run(app, args)
|
||||
} else {
|
||||
app.logf("Unknown command %q", line)
|
||||
}
|
||||
if err == errExitApp {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lookupCommand(prefix string) (name string, c command, ok bool) {
|
||||
prefix = strings.ToLower(prefix)
|
||||
if c, ok = commands[prefix]; ok {
|
||||
return prefix, c, ok
|
||||
}
|
||||
|
||||
for full, candidate := range commands {
|
||||
if strings.HasPrefix(full, prefix) {
|
||||
if c.run != nil {
|
||||
return "", command{}, false // ambiguous
|
||||
}
|
||||
c = candidate
|
||||
name = full
|
||||
}
|
||||
}
|
||||
return name, c, c.run != nil
|
||||
}
|
||||
|
||||
var errExitApp = errors.New("internal sentinel error value to quit the console reading loop")
|
||||
|
||||
func (a *h2i) cmdQuit(args []string) error {
|
||||
if len(args) > 0 {
|
||||
a.logf("the QUIT command takes no argument")
|
||||
return nil
|
||||
}
|
||||
return errExitApp
|
||||
}
|
||||
|
||||
func (a *h2i) cmdSettings(args []string) error {
|
||||
if len(args) == 1 && strings.EqualFold(args[0], "ACK") {
|
||||
return a.framer.WriteSettingsAck()
|
||||
}
|
||||
var settings []http2.Setting
|
||||
for _, arg := range args {
|
||||
if strings.EqualFold(arg, "ACK") {
|
||||
a.logf("Error: ACK must be only argument with the SETTINGS command")
|
||||
return nil
|
||||
}
|
||||
eq := strings.Index(arg, "=")
|
||||
if eq == -1 {
|
||||
a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
|
||||
return nil
|
||||
}
|
||||
sid, ok := settingByName(arg[:eq])
|
||||
if !ok {
|
||||
a.logf("Error: unknown setting name %q", arg[:eq])
|
||||
return nil
|
||||
}
|
||||
val, err := strconv.ParseUint(arg[eq+1:], 10, 32)
|
||||
if err != nil {
|
||||
a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
|
||||
return nil
|
||||
}
|
||||
settings = append(settings, http2.Setting{
|
||||
ID: sid,
|
||||
Val: uint32(val),
|
||||
})
|
||||
}
|
||||
a.logf("Sending: %v", settings)
|
||||
return a.framer.WriteSettings(settings...)
|
||||
}
|
||||
|
||||
func settingByName(name string) (http2.SettingID, bool) {
|
||||
for _, sid := range [...]http2.SettingID{
|
||||
http2.SettingHeaderTableSize,
|
||||
http2.SettingEnablePush,
|
||||
http2.SettingMaxConcurrentStreams,
|
||||
http2.SettingInitialWindowSize,
|
||||
http2.SettingMaxFrameSize,
|
||||
http2.SettingMaxHeaderListSize,
|
||||
} {
|
||||
if strings.EqualFold(sid.String(), name) {
|
||||
return sid, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (app *h2i) cmdPing(args []string) error {
|
||||
if len(args) > 1 {
|
||||
app.logf("invalid PING usage: only accepts 0 or 1 args")
|
||||
return nil // nil means don't end the program
|
||||
}
|
||||
var data [8]byte
|
||||
if len(args) == 1 {
|
||||
copy(data[:], args[0])
|
||||
} else {
|
||||
copy(data[:], "h2i_ping")
|
||||
}
|
||||
return app.framer.WritePing(false, data)
|
||||
}
|
||||
|
||||
func (app *h2i) cmdHeaders(args []string) error {
|
||||
if len(args) > 0 {
|
||||
app.logf("Error: HEADERS doesn't yet take arguments.")
|
||||
// TODO: flags for restricting window size, to force CONTINUATION
|
||||
// frames.
|
||||
return nil
|
||||
}
|
||||
var h1req bytes.Buffer
|
||||
app.term.SetPrompt("(as HTTP/1.1)> ")
|
||||
defer app.term.SetPrompt("h2i> ")
|
||||
for {
|
||||
line, err := app.term.ReadLine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h1req.WriteString(line)
|
||||
h1req.WriteString("\r\n")
|
||||
if line == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
req, err := http.ReadRequest(bufio.NewReader(&h1req))
|
||||
if err != nil {
|
||||
app.logf("Invalid HTTP/1.1 request: %v", err)
|
||||
return nil
|
||||
}
|
||||
if app.streamID == 0 {
|
||||
app.streamID = 1
|
||||
} else {
|
||||
app.streamID += 2
|
||||
}
|
||||
app.logf("Opening Stream-ID %d:", app.streamID)
|
||||
hbf := app.encodeHeaders(req)
|
||||
if len(hbf) > 16<<10 {
|
||||
app.logf("TODO: h2i doesn't yet write CONTINUATION frames. Copy it from transport.go")
|
||||
return nil
|
||||
}
|
||||
return app.framer.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: app.streamID,
|
||||
BlockFragment: hbf,
|
||||
EndStream: req.Method == "GET" || req.Method == "HEAD", // good enough for now
|
||||
EndHeaders: true, // for now
|
||||
})
|
||||
}
|
||||
|
||||
func (app *h2i) readFrames() error {
|
||||
for {
|
||||
f, err := app.framer.ReadFrame()
|
||||
if err != nil {
|
||||
return fmt.Errorf("ReadFrame: %v", err)
|
||||
}
|
||||
app.logf("%v", f)
|
||||
switch f := f.(type) {
|
||||
case *http2.PingFrame:
|
||||
app.logf(" Data = %q", f.Data)
|
||||
case *http2.SettingsFrame:
|
||||
f.ForeachSetting(func(s http2.Setting) error {
|
||||
app.logf(" %v", s)
|
||||
app.peerSetting[s.ID] = s.Val
|
||||
return nil
|
||||
})
|
||||
case *http2.WindowUpdateFrame:
|
||||
app.logf(" Window-Increment = %v\n", f.Increment)
|
||||
case *http2.GoAwayFrame:
|
||||
app.logf(" Last-Stream-ID = %d; Error-Code = %v (%d)\n", f.LastStreamID, f.ErrCode, f.ErrCode)
|
||||
case *http2.DataFrame:
|
||||
app.logf(" %q", f.Data())
|
||||
case *http2.HeadersFrame:
|
||||
if f.HasPriority() {
|
||||
app.logf(" PRIORITY = %v", f.Priority)
|
||||
}
|
||||
if app.hdec == nil {
|
||||
// TODO: if the user uses h2i to send a SETTINGS frame advertising
|
||||
// something larger, we'll need to respect SETTINGS_HEADER_TABLE_SIZE
|
||||
// and stuff here instead of using the 4k default. But for now:
|
||||
tableSize := uint32(4 << 10)
|
||||
app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
|
||||
}
|
||||
app.hdec.Write(f.HeaderBlockFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called from readLoop
|
||||
func (app *h2i) onNewHeaderField(f hpack.HeaderField) {
|
||||
if f.Sensitive {
|
||||
app.logf(" %s = %q (SENSITIVE)", f.Name, f.Value)
|
||||
}
|
||||
app.logf(" %s = %q", f.Name, f.Value)
|
||||
}
|
||||
|
||||
func (app *h2i) encodeHeaders(req *http.Request) []byte {
|
||||
app.hbuf.Reset()
|
||||
|
||||
// TODO(bradfitz): figure out :authority-vs-Host stuff between http2 and Go
|
||||
host := req.Host
|
||||
if host == "" {
|
||||
host = req.URL.Host
|
||||
}
|
||||
|
||||
path := req.URL.Path
|
||||
if path == "" {
|
||||
path = "/"
|
||||
}
|
||||
|
||||
app.writeHeader(":authority", host) // probably not right for all sites
|
||||
app.writeHeader(":method", req.Method)
|
||||
app.writeHeader(":path", path)
|
||||
app.writeHeader(":scheme", "https")
|
||||
|
||||
for k, vv := range req.Header {
|
||||
lowKey := strings.ToLower(k)
|
||||
if lowKey == "host" {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
app.writeHeader(lowKey, v)
|
||||
}
|
||||
}
|
||||
return app.hbuf.Bytes()
|
||||
}
|
||||
|
||||
func (app *h2i) writeHeader(name, value string) {
|
||||
app.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
|
||||
app.logf(" %s = %s", name, value)
|
||||
}
|
5021
vendor/golang.org/x/net/http2/testdata/draft-ietf-httpbis-http2.xml
generated
vendored
5021
vendor/golang.org/x/net/http2/testdata/draft-ietf-httpbis-http2.xml
generated
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user