瀏覽代碼

Bump golang.org/x/net to go1.10 release commit

The primary need for this is x/net/context now is just a type alias to
the stdlib context package.
This makes issues with conflicts between "golang.org/x/net/context" and
the stdib "context" go away (primarily a concern in interface
definitions/implementations).

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Brian Goff 7 年之前
父節點
當前提交
848ef1da8b

+ 1 - 1
vendor.conf

@@ -13,7 +13,7 @@ github.com/mattn/go-shellwords v1.0.3
 github.com/sirupsen/logrus v1.0.3
 github.com/sirupsen/logrus v1.0.3
 github.com/tchap/go-patricia v2.2.6
 github.com/tchap/go-patricia v2.2.6
 github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
 github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
-golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6
+golang.org/x/net 5561cd9b4330353950f399814f427425c0a26fd2
 golang.org/x/sys 37707fdb30a5b38865cfb95e5aab41707daec7fd
 golang.org/x/sys 37707fdb30a5b38865cfb95e5aab41707daec7fd
 github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
 github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
 github.com/docker/go-connections 7beb39f0b969b075d1325fecb092faf27fd357b6
 github.com/docker/go-connections 7beb39f0b969b075d1325fecb092faf27fd357b6

+ 0 - 3
vendor/golang.org/x/net/README

@@ -1,3 +0,0 @@
-This repository holds supplementary Go networking libraries.
-
-To submit changes to this repository, see http://golang.org/doc/contribute.html.

+ 16 - 0
vendor/golang.org/x/net/README.md

@@ -0,0 +1,16 @@
+# Go Networking
+
+This repository holds supplementary Go networking libraries.
+
+## Download/Install
+
+The easiest way to install is to run `go get -u golang.org/x/net`. You can
+also manually git clone the repository to `$GOPATH/src/golang.org/x/net`.
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit
+changes to this repository, see https://golang.org/doc/contribute.html.
+The main issue tracker for the net repository is located at
+https://github.com/golang/go/issues. Prefix your issue with "x/net:" in the
+subject line, so it is easy to find.

+ 2 - 102
vendor/golang.org/x/net/context/context.go

@@ -5,6 +5,8 @@
 // Package context defines the Context type, which carries deadlines,
 // Package context defines the Context type, which carries deadlines,
 // cancelation signals, and other request-scoped values across API boundaries
 // cancelation signals, and other request-scoped values across API boundaries
 // and between processes.
 // and between processes.
+// As of Go 1.7 this package is available in the standard library under the
+// name context.  https://golang.org/pkg/context.
 //
 //
 // Incoming requests to a server should create a Context, and outgoing calls to
 // Incoming requests to a server should create a Context, and outgoing calls to
 // servers should accept a Context. The chain of function calls between must
 // servers should accept a Context. The chain of function calls between must
@@ -36,103 +38,6 @@
 // Contexts.
 // Contexts.
 package context // import "golang.org/x/net/context"
 package context // import "golang.org/x/net/context"
 
 
-import "time"
-
-// A Context carries a deadline, a cancelation signal, and other values across
-// API boundaries.
-//
-// Context's methods may be called by multiple goroutines simultaneously.
-type Context interface {
-	// Deadline returns the time when work done on behalf of this context
-	// should be canceled. Deadline returns ok==false when no deadline is
-	// set. Successive calls to Deadline return the same results.
-	Deadline() (deadline time.Time, ok bool)
-
-	// Done returns a channel that's closed when work done on behalf of this
-	// context should be canceled. Done may return nil if this context can
-	// never be canceled. Successive calls to Done return the same value.
-	//
-	// WithCancel arranges for Done to be closed when cancel is called;
-	// WithDeadline arranges for Done to be closed when the deadline
-	// expires; WithTimeout arranges for Done to be closed when the timeout
-	// elapses.
-	//
-	// Done is provided for use in select statements:
-	//
-	//  // Stream generates values with DoSomething and sends them to out
-	//  // until DoSomething returns an error or ctx.Done is closed.
-	//  func Stream(ctx context.Context, out chan<- Value) error {
-	//  	for {
-	//  		v, err := DoSomething(ctx)
-	//  		if err != nil {
-	//  			return err
-	//  		}
-	//  		select {
-	//  		case <-ctx.Done():
-	//  			return ctx.Err()
-	//  		case out <- v:
-	//  		}
-	//  	}
-	//  }
-	//
-	// See http://blog.golang.org/pipelines for more examples of how to use
-	// a Done channel for cancelation.
-	Done() <-chan struct{}
-
-	// Err returns a non-nil error value after Done is closed. Err returns
-	// Canceled if the context was canceled or DeadlineExceeded if the
-	// context's deadline passed. No other values for Err are defined.
-	// After Done is closed, successive calls to Err return the same value.
-	Err() error
-
-	// Value returns the value associated with this context for key, or nil
-	// if no value is associated with key. Successive calls to Value with
-	// the same key returns the same result.
-	//
-	// Use context values only for request-scoped data that transits
-	// processes and API boundaries, not for passing optional parameters to
-	// functions.
-	//
-	// A key identifies a specific value in a Context. Functions that wish
-	// to store values in Context typically allocate a key in a global
-	// variable then use that key as the argument to context.WithValue and
-	// Context.Value. A key can be any type that supports equality;
-	// packages should define keys as an unexported type to avoid
-	// collisions.
-	//
-	// Packages that define a Context key should provide type-safe accessors
-	// for the values stores using that key:
-	//
-	// 	// Package user defines a User type that's stored in Contexts.
-	// 	package user
-	//
-	// 	import "golang.org/x/net/context"
-	//
-	// 	// User is the type of value stored in the Contexts.
-	// 	type User struct {...}
-	//
-	// 	// key is an unexported type for keys defined in this package.
-	// 	// This prevents collisions with keys defined in other packages.
-	// 	type key int
-	//
-	// 	// userKey is the key for user.User values in Contexts. It is
-	// 	// unexported; clients use user.NewContext and user.FromContext
-	// 	// instead of using this key directly.
-	// 	var userKey key = 0
-	//
-	// 	// NewContext returns a new Context that carries value u.
-	// 	func NewContext(ctx context.Context, u *User) context.Context {
-	// 		return context.WithValue(ctx, userKey, u)
-	// 	}
-	//
-	// 	// FromContext returns the User value stored in ctx, if any.
-	// 	func FromContext(ctx context.Context) (*User, bool) {
-	// 		u, ok := ctx.Value(userKey).(*User)
-	// 		return u, ok
-	// 	}
-	Value(key interface{}) interface{}
-}
-
 // Background returns a non-nil, empty Context. It is never canceled, has no
 // Background returns a non-nil, empty Context. It is never canceled, has no
 // values, and has no deadline. It is typically used by the main function,
 // values, and has no deadline. It is typically used by the main function,
 // initialization, and tests, and as the top-level Context for incoming
 // initialization, and tests, and as the top-level Context for incoming
@@ -149,8 +54,3 @@ func Background() Context {
 func TODO() Context {
 func TODO() Context {
 	return todo
 	return todo
 }
 }
-
-// A CancelFunc tells an operation to abandon its work.
-// A CancelFunc does not wait for the work to stop.
-// After the first call, subsequent calls to a CancelFunc do nothing.
-type CancelFunc func()

+ 20 - 0
vendor/golang.org/x/net/context/go19.go

@@ -0,0 +1,20 @@
+// Copyright 2017 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 go1.9
+
+package context
+
+import "context" // standard library's context, as of Go 1.7
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context = context.Context
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc = context.CancelFunc

+ 109 - 0
vendor/golang.org/x/net/context/pre_go19.go

@@ -0,0 +1,109 @@
+// 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 !go1.9
+
+package context
+
+import "time"
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context interface {
+	// Deadline returns the time when work done on behalf of this context
+	// should be canceled. Deadline returns ok==false when no deadline is
+	// set. Successive calls to Deadline return the same results.
+	Deadline() (deadline time.Time, ok bool)
+
+	// Done returns a channel that's closed when work done on behalf of this
+	// context should be canceled. Done may return nil if this context can
+	// never be canceled. Successive calls to Done return the same value.
+	//
+	// WithCancel arranges for Done to be closed when cancel is called;
+	// WithDeadline arranges for Done to be closed when the deadline
+	// expires; WithTimeout arranges for Done to be closed when the timeout
+	// elapses.
+	//
+	// Done is provided for use in select statements:
+	//
+	//  // Stream generates values with DoSomething and sends them to out
+	//  // until DoSomething returns an error or ctx.Done is closed.
+	//  func Stream(ctx context.Context, out chan<- Value) error {
+	//  	for {
+	//  		v, err := DoSomething(ctx)
+	//  		if err != nil {
+	//  			return err
+	//  		}
+	//  		select {
+	//  		case <-ctx.Done():
+	//  			return ctx.Err()
+	//  		case out <- v:
+	//  		}
+	//  	}
+	//  }
+	//
+	// See http://blog.golang.org/pipelines for more examples of how to use
+	// a Done channel for cancelation.
+	Done() <-chan struct{}
+
+	// Err returns a non-nil error value after Done is closed. Err returns
+	// Canceled if the context was canceled or DeadlineExceeded if the
+	// context's deadline passed. No other values for Err are defined.
+	// After Done is closed, successive calls to Err return the same value.
+	Err() error
+
+	// Value returns the value associated with this context for key, or nil
+	// if no value is associated with key. Successive calls to Value with
+	// the same key returns the same result.
+	//
+	// Use context values only for request-scoped data that transits
+	// processes and API boundaries, not for passing optional parameters to
+	// functions.
+	//
+	// A key identifies a specific value in a Context. Functions that wish
+	// to store values in Context typically allocate a key in a global
+	// variable then use that key as the argument to context.WithValue and
+	// Context.Value. A key can be any type that supports equality;
+	// packages should define keys as an unexported type to avoid
+	// collisions.
+	//
+	// Packages that define a Context key should provide type-safe accessors
+	// for the values stores using that key:
+	//
+	// 	// Package user defines a User type that's stored in Contexts.
+	// 	package user
+	//
+	// 	import "golang.org/x/net/context"
+	//
+	// 	// User is the type of value stored in the Contexts.
+	// 	type User struct {...}
+	//
+	// 	// key is an unexported type for keys defined in this package.
+	// 	// This prevents collisions with keys defined in other packages.
+	// 	type key int
+	//
+	// 	// userKey is the key for user.User values in Contexts. It is
+	// 	// unexported; clients use user.NewContext and user.FromContext
+	// 	// instead of using this key directly.
+	// 	var userKey key = 0
+	//
+	// 	// NewContext returns a new Context that carries value u.
+	// 	func NewContext(ctx context.Context, u *User) context.Context {
+	// 		return context.WithValue(ctx, userKey, u)
+	// 	}
+	//
+	// 	// FromContext returns the User value stored in ctx, if any.
+	// 	func FromContext(ctx context.Context) (*User, bool) {
+	// 		u, ok := ctx.Value(userKey).(*User)
+	// 		return u, ok
+	// 	}
+	Value(key interface{}) interface{}
+}
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc func()

+ 1 - 1
vendor/golang.org/x/net/http2/configure_transport.go

@@ -56,7 +56,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) {
 }
 }
 
 
 // registerHTTPSProtocol calls Transport.RegisterProtocol but
 // registerHTTPSProtocol calls Transport.RegisterProtocol but
-// convering panics into errors.
+// converting panics into errors.
 func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
 func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
 	defer func() {
 	defer func() {
 		if e := recover(); e != nil {
 		if e := recover(); e != nil {

+ 8 - 5
vendor/golang.org/x/net/http2/errors.go

@@ -87,13 +87,16 @@ type goAwayFlowError struct{}
 
 
 func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
 func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
 
 
-// connErrorReason wraps a ConnectionError with an informative error about why it occurs.
-
+// connError represents an HTTP/2 ConnectionError error code, along
+// with a string (for debugging) explaining why.
+//
 // Errors of this type are only returned by the frame parser functions
 // Errors of this type are only returned by the frame parser functions
-// and converted into ConnectionError(ErrCodeProtocol).
+// and converted into ConnectionError(Code), after stashing away
+// the Reason into the Framer's errDetail field, accessible via
+// the (*Framer).ErrorDetail method.
 type connError struct {
 type connError struct {
-	Code   ErrCode
-	Reason string
+	Code   ErrCode // the ConnectionError error code
+	Reason string  // additional reason
 }
 }
 
 
 func (e connError) Error() string {
 func (e connError) Error() string {

+ 2 - 0
vendor/golang.org/x/net/http2/go18.go

@@ -52,3 +52,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
 func reqBodyIsNoBody(body io.ReadCloser) bool {
 func reqBodyIsNoBody(body io.ReadCloser) bool {
 	return body == http.NoBody
 	return body == http.NoBody
 }
 }
+
+func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only

+ 6 - 2
vendor/golang.org/x/net/http2/http2.go

@@ -376,12 +376,16 @@ func (s *sorter) SortStrings(ss []string) {
 // validPseudoPath reports whether v is a valid :path pseudo-header
 // validPseudoPath reports whether v is a valid :path pseudo-header
 // value. It must be either:
 // value. It must be either:
 //
 //
-//     *) a non-empty string starting with '/', but not with with "//",
+//     *) a non-empty string starting with '/'
 //     *) the string '*', for OPTIONS requests.
 //     *) the string '*', for OPTIONS requests.
 //
 //
 // For now this is only used a quick check for deciding when to clean
 // For now this is only used a quick check for deciding when to clean
 // up Opaque URLs before sending requests from the Transport.
 // up Opaque URLs before sending requests from the Transport.
 // See golang.org/issue/16847
 // See golang.org/issue/16847
+//
+// We used to enforce that the path also didn't start with "//", but
+// Google's GFE accepts such paths and Chrome sends them, so ignore
+// that part of the spec. See golang.org/issue/19103.
 func validPseudoPath(v string) bool {
 func validPseudoPath(v string) bool {
-	return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
+	return (len(v) > 0 && v[0] == '/') || v == "*"
 }
 }

+ 2 - 0
vendor/golang.org/x/net/http2/not_go18.go

@@ -25,3 +25,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
 }
 }
 
 
 func reqBodyIsNoBody(io.ReadCloser) bool { return false }
 func reqBodyIsNoBody(io.ReadCloser) bool { return false }
+
+func go18httpNoBody() io.ReadCloser { return nil } // for tests only

+ 1 - 1
vendor/golang.org/x/net/http2/pipe.go

@@ -50,7 +50,7 @@ func (p *pipe) Read(d []byte) (n int, err error) {
 		if p.breakErr != nil {
 		if p.breakErr != nil {
 			return 0, p.breakErr
 			return 0, p.breakErr
 		}
 		}
-		if p.b.Len() > 0 {
+		if p.b != nil && p.b.Len() > 0 {
 			return p.b.Read(d)
 			return p.b.Read(d)
 		}
 		}
 		if p.err != nil {
 		if p.err != nil {

+ 41 - 20
vendor/golang.org/x/net/http2/server.go

@@ -853,8 +853,13 @@ func (sc *serverConn) serve() {
 			}
 			}
 		}
 		}
 
 
-		if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame {
-			return
+		// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
+		// with no error code (graceful shutdown), don't start the timer until
+		// all open streams have been completed.
+		sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
+		gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
+		if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
+			sc.shutDownIn(goAwayTimeout)
 		}
 		}
 	}
 	}
 }
 }
@@ -1218,30 +1223,31 @@ func (sc *serverConn) startGracefulShutdown() {
 	sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
 	sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
 }
 }
 
 
+// After sending GOAWAY, the connection will close after goAwayTimeout.
+// If we close the connection immediately after sending GOAWAY, there may
+// be unsent data in our kernel receive buffer, which will cause the kernel
+// to send a TCP RST on close() instead of a FIN. This RST will abort the
+// connection immediately, whether or not the client had received the GOAWAY.
+//
+// Ideally we should delay for at least 1 RTT + epsilon so the client has
+// a chance to read the GOAWAY and stop sending messages. Measuring RTT
+// is hard, so we approximate with 1 second. See golang.org/issue/18701.
+//
+// This is a var so it can be shorter in tests, where all requests uses the
+// loopback interface making the expected RTT very small.
+//
+// TODO: configurable?
+var goAwayTimeout = 1 * time.Second
+
 func (sc *serverConn) startGracefulShutdownInternal() {
 func (sc *serverConn) startGracefulShutdownInternal() {
-	sc.goAwayIn(ErrCodeNo, 0)
+	sc.goAway(ErrCodeNo)
 }
 }
 
 
 func (sc *serverConn) goAway(code ErrCode) {
 func (sc *serverConn) goAway(code ErrCode) {
-	sc.serveG.check()
-	var forceCloseIn time.Duration
-	if code != ErrCodeNo {
-		forceCloseIn = 250 * time.Millisecond
-	} else {
-		// TODO: configurable
-		forceCloseIn = 1 * time.Second
-	}
-	sc.goAwayIn(code, forceCloseIn)
-}
-
-func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
 	sc.serveG.check()
 	sc.serveG.check()
 	if sc.inGoAway {
 	if sc.inGoAway {
 		return
 		return
 	}
 	}
-	if forceCloseIn != 0 {
-		sc.shutDownIn(forceCloseIn)
-	}
 	sc.inGoAway = true
 	sc.inGoAway = true
 	sc.needToSendGoAway = true
 	sc.needToSendGoAway = true
 	sc.goAwayCode = code
 	sc.goAwayCode = code
@@ -2252,6 +2258,7 @@ type responseWriterState struct {
 	wroteHeader   bool        // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
 	wroteHeader   bool        // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
 	sentHeader    bool        // have we sent the header frame?
 	sentHeader    bool        // have we sent the header frame?
 	handlerDone   bool        // handler has finished
 	handlerDone   bool        // handler has finished
+	dirty         bool        // a Write failed; don't reuse this responseWriterState
 
 
 	sentContentLen int64 // non-zero if handler set a Content-Length header
 	sentContentLen int64 // non-zero if handler set a Content-Length header
 	wroteBytes     int64
 	wroteBytes     int64
@@ -2333,6 +2340,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			date:          date,
 			date:          date,
 		})
 		})
 		if err != nil {
 		if err != nil {
+			rws.dirty = true
 			return 0, err
 			return 0, err
 		}
 		}
 		if endStream {
 		if endStream {
@@ -2354,6 +2362,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 	if len(p) > 0 || endStream {
 	if len(p) > 0 || endStream {
 		// only send a 0 byte DATA frame if we're ending the stream.
 		// only send a 0 byte DATA frame if we're ending the stream.
 		if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
 		if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
+			rws.dirty = true
 			return 0, err
 			return 0, err
 		}
 		}
 	}
 	}
@@ -2365,6 +2374,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
 			trailers:  rws.trailers,
 			trailers:  rws.trailers,
 			endStream: true,
 			endStream: true,
 		})
 		})
+		if err != nil {
+			rws.dirty = true
+		}
 		return len(p), err
 		return len(p), err
 	}
 	}
 	return len(p), nil
 	return len(p), nil
@@ -2504,7 +2516,7 @@ func cloneHeader(h http.Header) http.Header {
 //
 //
 // * Handler calls w.Write or w.WriteString ->
 // * Handler calls w.Write or w.WriteString ->
 // * -> rws.bw (*bufio.Writer) ->
 // * -> rws.bw (*bufio.Writer) ->
-// * (Handler migth call Flush)
+// * (Handler might call Flush)
 // * -> chunkWriter{rws}
 // * -> chunkWriter{rws}
 // * -> responseWriterState.writeChunk(p []byte)
 // * -> responseWriterState.writeChunk(p []byte)
 // * -> responseWriterState.writeChunk (most of the magic; see comment there)
 // * -> responseWriterState.writeChunk (most of the magic; see comment there)
@@ -2543,10 +2555,19 @@ func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int,
 
 
 func (w *responseWriter) handlerDone() {
 func (w *responseWriter) handlerDone() {
 	rws := w.rws
 	rws := w.rws
+	dirty := rws.dirty
 	rws.handlerDone = true
 	rws.handlerDone = true
 	w.Flush()
 	w.Flush()
 	w.rws = nil
 	w.rws = nil
-	responseWriterStatePool.Put(rws)
+	if !dirty {
+		// Only recycle the pool if all prior Write calls to
+		// the serverConn goroutine completed successfully. If
+		// they returned earlier due to resets from the peer
+		// there might still be write goroutines outstanding
+		// from the serverConn referencing the rws memory. See
+		// issue 20704.
+		responseWriterStatePool.Put(rws)
+	}
 }
 }
 
 
 // Push errors.
 // Push errors.

+ 302 - 140
vendor/golang.org/x/net/http2/transport.go

@@ -18,6 +18,7 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"log"
 	"log"
 	"math"
 	"math"
+	mathrand "math/rand"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
 	"sort"
 	"sort"
@@ -86,7 +87,7 @@ type Transport struct {
 
 
 	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
 	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
 	// send in the initial settings frame. It is how many bytes
 	// send in the initial settings frame. It is how many bytes
-	// of response headers are allow. Unlike the http2 spec, zero here
+	// of response headers are allowed. Unlike the http2 spec, zero here
 	// means to use a default limit (currently 10MB). If you actually
 	// means to use a default limit (currently 10MB). If you actually
 	// want to advertise an ulimited value to the peer, Transport
 	// want to advertise an ulimited value to the peer, Transport
 	// interprets the highest possible value here (0xffffffff or 1<<32-1)
 	// interprets the highest possible value here (0xffffffff or 1<<32-1)
@@ -164,15 +165,17 @@ type ClientConn struct {
 	goAwayDebug     string                   // goAway frame's debug data, retained as a string
 	goAwayDebug     string                   // goAway frame's debug data, retained as a string
 	streams         map[uint32]*clientStream // client-initiated
 	streams         map[uint32]*clientStream // client-initiated
 	nextStreamID    uint32
 	nextStreamID    uint32
+	pendingRequests int                       // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
 	pings           map[[8]byte]chan struct{} // in flight ping data to notification channel
 	pings           map[[8]byte]chan struct{} // in flight ping data to notification channel
 	bw              *bufio.Writer
 	bw              *bufio.Writer
 	br              *bufio.Reader
 	br              *bufio.Reader
 	fr              *Framer
 	fr              *Framer
 	lastActive      time.Time
 	lastActive      time.Time
 	// Settings from peer: (also guarded by mu)
 	// Settings from peer: (also guarded by mu)
-	maxFrameSize         uint32
-	maxConcurrentStreams uint32
-	initialWindowSize    uint32
+	maxFrameSize          uint32
+	maxConcurrentStreams  uint32
+	peerMaxHeaderListSize uint64
+	initialWindowSize     uint32
 
 
 	hbuf    bytes.Buffer // HPACK encoder writes into this
 	hbuf    bytes.Buffer // HPACK encoder writes into this
 	henc    *hpack.Encoder
 	henc    *hpack.Encoder
@@ -216,35 +219,45 @@ type clientStream struct {
 	resTrailer *http.Header // client's Response.Trailer
 	resTrailer *http.Header // client's Response.Trailer
 }
 }
 
 
-// awaitRequestCancel runs in its own goroutine and waits for the user
-// to cancel a RoundTrip request, its context to expire, or for the
-// request to be done (any way it might be removed from the cc.streams
-// map: peer reset, successful completion, TCP connection breakage,
-// etc)
-func (cs *clientStream) awaitRequestCancel(req *http.Request) {
+// awaitRequestCancel waits for the user to cancel a request or for the done
+// channel to be signaled. A non-nil error is returned only if the request was
+// canceled.
+func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
 	ctx := reqContext(req)
 	ctx := reqContext(req)
 	if req.Cancel == nil && ctx.Done() == nil {
 	if req.Cancel == nil && ctx.Done() == nil {
-		return
+		return nil
 	}
 	}
 	select {
 	select {
 	case <-req.Cancel:
 	case <-req.Cancel:
-		cs.cancelStream()
-		cs.bufPipe.CloseWithError(errRequestCanceled)
+		return errRequestCanceled
 	case <-ctx.Done():
 	case <-ctx.Done():
+		return ctx.Err()
+	case <-done:
+		return nil
+	}
+}
+
+// awaitRequestCancel waits for the user to cancel a request, its context to
+// expire, or for the request to be done (any way it might be removed from the
+// cc.streams map: peer reset, successful completion, TCP connection breakage,
+// etc). If the request is canceled, then cs will be canceled and closed.
+func (cs *clientStream) awaitRequestCancel(req *http.Request) {
+	if err := awaitRequestCancel(req, cs.done); err != nil {
 		cs.cancelStream()
 		cs.cancelStream()
-		cs.bufPipe.CloseWithError(ctx.Err())
-	case <-cs.done:
+		cs.bufPipe.CloseWithError(err)
 	}
 	}
 }
 }
 
 
 func (cs *clientStream) cancelStream() {
 func (cs *clientStream) cancelStream() {
-	cs.cc.mu.Lock()
+	cc := cs.cc
+	cc.mu.Lock()
 	didReset := cs.didReset
 	didReset := cs.didReset
 	cs.didReset = true
 	cs.didReset = true
-	cs.cc.mu.Unlock()
+	cc.mu.Unlock()
 
 
 	if !didReset {
 	if !didReset {
-		cs.cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+		cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+		cc.forgetStreamID(cs.ID)
 	}
 	}
 }
 }
 
 
@@ -329,7 +342,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
 	}
 	}
 
 
 	addr := authorityAddr(req.URL.Scheme, req.URL.Host)
 	addr := authorityAddr(req.URL.Scheme, req.URL.Host)
-	for {
+	for retry := 0; ; retry++ {
 		cc, err := t.connPool().GetClientConn(req, addr)
 		cc, err := t.connPool().GetClientConn(req, addr)
 		if err != nil {
 		if err != nil {
 			t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
 			t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
@@ -337,9 +350,25 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
 		}
 		}
 		traceGotConn(req, cc)
 		traceGotConn(req, cc)
 		res, err := cc.RoundTrip(req)
 		res, err := cc.RoundTrip(req)
-		if err != nil {
-			if req, err = shouldRetryRequest(req, err); err == nil {
-				continue
+		if err != nil && retry <= 6 {
+			afterBodyWrite := false
+			if e, ok := err.(afterReqBodyWriteError); ok {
+				err = e
+				afterBodyWrite = true
+			}
+			if req, err = shouldRetryRequest(req, err, afterBodyWrite); err == nil {
+				// After the first retry, do exponential backoff with 10% jitter.
+				if retry == 0 {
+					continue
+				}
+				backoff := float64(uint(1) << (uint(retry) - 1))
+				backoff += backoff * (0.1 * mathrand.Float64())
+				select {
+				case <-time.After(time.Second * time.Duration(backoff)):
+					continue
+				case <-reqContext(req).Done():
+					return nil, reqContext(req).Err()
+				}
 			}
 			}
 		}
 		}
 		if err != nil {
 		if err != nil {
@@ -360,43 +389,60 @@ func (t *Transport) CloseIdleConnections() {
 }
 }
 
 
 var (
 var (
-	errClientConnClosed   = errors.New("http2: client conn is closed")
-	errClientConnUnusable = errors.New("http2: client conn not usable")
-
-	errClientConnGotGoAway                 = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
-	errClientConnGotGoAwayAfterSomeReqBody = errors.New("http2: Transport received Server's graceful shutdown GOAWAY; some request body already written")
+	errClientConnClosed    = errors.New("http2: client conn is closed")
+	errClientConnUnusable  = errors.New("http2: client conn not usable")
+	errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
 )
 )
 
 
+// afterReqBodyWriteError is a wrapper around errors returned by ClientConn.RoundTrip.
+// It is used to signal that err happened after part of Request.Body was sent to the server.
+type afterReqBodyWriteError struct {
+	err error
+}
+
+func (e afterReqBodyWriteError) Error() string {
+	return e.err.Error() + "; some request body already written"
+}
+
 // shouldRetryRequest is called by RoundTrip when a request fails to get
 // shouldRetryRequest is called by RoundTrip when a request fails to get
 // response headers. It is always called with a non-nil error.
 // response headers. It is always called with a non-nil error.
 // It returns either a request to retry (either the same request, or a
 // It returns either a request to retry (either the same request, or a
 // modified clone), or an error if the request can't be replayed.
 // modified clone), or an error if the request can't be replayed.
-func shouldRetryRequest(req *http.Request, err error) (*http.Request, error) {
-	switch err {
-	default:
+func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*http.Request, error) {
+	if !canRetryError(err) {
 		return nil, err
 		return nil, err
-	case errClientConnUnusable, errClientConnGotGoAway:
+	}
+	if !afterBodyWrite {
 		return req, nil
 		return req, nil
-	case errClientConnGotGoAwayAfterSomeReqBody:
-		// If the Body is nil (or http.NoBody), it's safe to reuse
-		// this request and its Body.
-		if req.Body == nil || reqBodyIsNoBody(req.Body) {
-			return req, nil
-		}
-		// Otherwise we depend on the Request having its GetBody
-		// func defined.
-		getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
-		if getBody == nil {
-			return nil, errors.New("http2: Transport: peer server initiated graceful shutdown after some of Request.Body was written; define Request.GetBody to avoid this error")
-		}
-		body, err := getBody()
-		if err != nil {
-			return nil, err
-		}
-		newReq := *req
-		newReq.Body = body
-		return &newReq, nil
 	}
 	}
+	// If the Body is nil (or http.NoBody), it's safe to reuse
+	// this request and its Body.
+	if req.Body == nil || reqBodyIsNoBody(req.Body) {
+		return req, nil
+	}
+	// Otherwise we depend on the Request having its GetBody
+	// func defined.
+	getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
+	if getBody == nil {
+		return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
+	}
+	body, err := getBody()
+	if err != nil {
+		return nil, err
+	}
+	newReq := *req
+	newReq.Body = body
+	return &newReq, nil
+}
+
+func canRetryError(err error) bool {
+	if err == errClientConnUnusable || err == errClientConnGotGoAway {
+		return true
+	}
+	if se, ok := err.(StreamError); ok {
+		return se.Code == ErrCodeRefusedStream
+	}
+	return false
 }
 }
 
 
 func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
 func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
@@ -474,17 +520,18 @@ func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
 
 
 func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
 func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
 	cc := &ClientConn{
 	cc := &ClientConn{
-		t:                    t,
-		tconn:                c,
-		readerDone:           make(chan struct{}),
-		nextStreamID:         1,
-		maxFrameSize:         16 << 10, // spec default
-		initialWindowSize:    65535,    // spec default
-		maxConcurrentStreams: 1000,     // "infinite", per spec. 1000 seems good enough.
-		streams:              make(map[uint32]*clientStream),
-		singleUse:            singleUse,
-		wantSettingsAck:      true,
-		pings:                make(map[[8]byte]chan struct{}),
+		t:                     t,
+		tconn:                 c,
+		readerDone:            make(chan struct{}),
+		nextStreamID:          1,
+		maxFrameSize:          16 << 10,           // spec default
+		initialWindowSize:     65535,              // spec default
+		maxConcurrentStreams:  1000,               // "infinite", per spec. 1000 seems good enough.
+		peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
+		streams:               make(map[uint32]*clientStream),
+		singleUse:             singleUse,
+		wantSettingsAck:       true,
+		pings:                 make(map[[8]byte]chan struct{}),
 	}
 	}
 	if d := t.idleConnTimeout(); d != 0 {
 	if d := t.idleConnTimeout(); d != 0 {
 		cc.idleTimeout = d
 		cc.idleTimeout = d
@@ -560,6 +607,8 @@ func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
 	}
 	}
 }
 }
 
 
+// CanTakeNewRequest reports whether the connection can take a new request,
+// meaning it has not been closed or received or sent a GOAWAY.
 func (cc *ClientConn) CanTakeNewRequest() bool {
 func (cc *ClientConn) CanTakeNewRequest() bool {
 	cc.mu.Lock()
 	cc.mu.Lock()
 	defer cc.mu.Unlock()
 	defer cc.mu.Unlock()
@@ -571,8 +620,7 @@ func (cc *ClientConn) canTakeNewRequestLocked() bool {
 		return false
 		return false
 	}
 	}
 	return cc.goAway == nil && !cc.closed &&
 	return cc.goAway == nil && !cc.closed &&
-		int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
-		cc.nextStreamID < math.MaxInt32
+		int64(cc.nextStreamID)+int64(cc.pendingRequests) < math.MaxInt32
 }
 }
 
 
 // onIdleTimeout is called from a time.AfterFunc goroutine. It will
 // onIdleTimeout is called from a time.AfterFunc goroutine. It will
@@ -694,7 +742,7 @@ func checkConnHeaders(req *http.Request) error {
 // req.ContentLength, where 0 actually means zero (not unknown) and -1
 // req.ContentLength, where 0 actually means zero (not unknown) and -1
 // means unknown.
 // means unknown.
 func actualContentLength(req *http.Request) int64 {
 func actualContentLength(req *http.Request) int64 {
-	if req.Body == nil {
+	if req.Body == nil || reqBodyIsNoBody(req.Body) {
 		return 0
 		return 0
 	}
 	}
 	if req.ContentLength != 0 {
 	if req.ContentLength != 0 {
@@ -718,15 +766,14 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 	hasTrailers := trailers != ""
 	hasTrailers := trailers != ""
 
 
 	cc.mu.Lock()
 	cc.mu.Lock()
-	cc.lastActive = time.Now()
-	if cc.closed || !cc.canTakeNewRequestLocked() {
+	if err := cc.awaitOpenSlotForRequest(req); err != nil {
 		cc.mu.Unlock()
 		cc.mu.Unlock()
-		return nil, errClientConnUnusable
+		return nil, err
 	}
 	}
 
 
 	body := req.Body
 	body := req.Body
-	hasBody := body != nil
 	contentLen := actualContentLength(req)
 	contentLen := actualContentLength(req)
+	hasBody := contentLen != 0
 
 
 	// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
 	// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
 	var requestedGzip bool
 	var requestedGzip bool
@@ -816,14 +863,13 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 			cs.abortRequestBodyWrite(errStopReqBodyWrite)
 			cs.abortRequestBodyWrite(errStopReqBodyWrite)
 		}
 		}
 		if re.err != nil {
 		if re.err != nil {
-			if re.err == errClientConnGotGoAway {
-				cc.mu.Lock()
-				if cs.startedWrite {
-					re.err = errClientConnGotGoAwayAfterSomeReqBody
-				}
-				cc.mu.Unlock()
-			}
+			cc.mu.Lock()
+			afterBodyWrite := cs.startedWrite
+			cc.mu.Unlock()
 			cc.forgetStreamID(cs.ID)
 			cc.forgetStreamID(cs.ID)
+			if afterBodyWrite {
+				return nil, afterReqBodyWriteError{re.err}
+			}
 			return nil, re.err
 			return nil, re.err
 		}
 		}
 		res.Request = req
 		res.Request = req
@@ -836,31 +882,31 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 		case re := <-readLoopResCh:
 		case re := <-readLoopResCh:
 			return handleReadLoopResponse(re)
 			return handleReadLoopResponse(re)
 		case <-respHeaderTimer:
 		case <-respHeaderTimer:
-			cc.forgetStreamID(cs.ID)
 			if !hasBody || bodyWritten {
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 			} else {
 				bodyWriter.cancel()
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
 			}
+			cc.forgetStreamID(cs.ID)
 			return nil, errTimeout
 			return nil, errTimeout
 		case <-ctx.Done():
 		case <-ctx.Done():
-			cc.forgetStreamID(cs.ID)
 			if !hasBody || bodyWritten {
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 			} else {
 				bodyWriter.cancel()
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
 			}
+			cc.forgetStreamID(cs.ID)
 			return nil, ctx.Err()
 			return nil, ctx.Err()
 		case <-req.Cancel:
 		case <-req.Cancel:
-			cc.forgetStreamID(cs.ID)
 			if !hasBody || bodyWritten {
 			if !hasBody || bodyWritten {
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 				cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
 			} else {
 			} else {
 				bodyWriter.cancel()
 				bodyWriter.cancel()
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 				cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
 			}
 			}
+			cc.forgetStreamID(cs.ID)
 			return nil, errRequestCanceled
 			return nil, errRequestCanceled
 		case <-cs.peerReset:
 		case <-cs.peerReset:
 			// processResetStream already removed the
 			// processResetStream already removed the
@@ -887,6 +933,45 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 	}
 	}
 }
 }
 
 
+// awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams.
+// Must hold cc.mu.
+func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
+	var waitingForConn chan struct{}
+	var waitingForConnErr error // guarded by cc.mu
+	for {
+		cc.lastActive = time.Now()
+		if cc.closed || !cc.canTakeNewRequestLocked() {
+			return errClientConnUnusable
+		}
+		if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
+			if waitingForConn != nil {
+				close(waitingForConn)
+			}
+			return nil
+		}
+		// Unfortunately, we cannot wait on a condition variable and channel at
+		// the same time, so instead, we spin up a goroutine to check if the
+		// request is canceled while we wait for a slot to open in the connection.
+		if waitingForConn == nil {
+			waitingForConn = make(chan struct{})
+			go func() {
+				if err := awaitRequestCancel(req, waitingForConn); err != nil {
+					cc.mu.Lock()
+					waitingForConnErr = err
+					cc.cond.Broadcast()
+					cc.mu.Unlock()
+				}
+			}()
+		}
+		cc.pendingRequests++
+		cc.cond.Wait()
+		cc.pendingRequests--
+		if waitingForConnErr != nil {
+			return waitingForConnErr
+		}
+	}
+}
+
 // requires cc.wmu be held
 // requires cc.wmu be held
 func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte) error {
 func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte) error {
 	first := true // first frame written (HEADERS is first, then CONTINUATION)
 	first := true // first frame written (HEADERS is first, then CONTINUATION)
@@ -1002,8 +1087,13 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
 	var trls []byte
 	var trls []byte
 	if hasTrailers {
 	if hasTrailers {
 		cc.mu.Lock()
 		cc.mu.Lock()
-		defer cc.mu.Unlock()
-		trls = cc.encodeTrailers(req)
+		trls, err = cc.encodeTrailers(req)
+		cc.mu.Unlock()
+		if err != nil {
+			cc.writeStreamReset(cs.ID, ErrCodeInternal, err)
+			cc.forgetStreamID(cs.ID)
+			return err
+		}
 	}
 	}
 
 
 	cc.wmu.Lock()
 	cc.wmu.Lock()
@@ -1106,62 +1196,86 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
 		}
 		}
 	}
 	}
 
 
-	// 8.1.2.3 Request Pseudo-Header Fields
-	// The :path pseudo-header field includes the path and query parts of the
-	// target URI (the path-absolute production and optionally a '?' character
-	// followed by the query production (see Sections 3.3 and 3.4 of
-	// [RFC3986]).
-	cc.writeHeader(":authority", host)
-	cc.writeHeader(":method", req.Method)
-	if req.Method != "CONNECT" {
-		cc.writeHeader(":path", path)
-		cc.writeHeader(":scheme", req.URL.Scheme)
-	}
-	if trailers != "" {
-		cc.writeHeader("trailer", trailers)
-	}
+	enumerateHeaders := func(f func(name, value string)) {
+		// 8.1.2.3 Request Pseudo-Header Fields
+		// The :path pseudo-header field includes the path and query parts of the
+		// target URI (the path-absolute production and optionally a '?' character
+		// followed by the query production (see Sections 3.3 and 3.4 of
+		// [RFC3986]).
+		f(":authority", host)
+		f(":method", req.Method)
+		if req.Method != "CONNECT" {
+			f(":path", path)
+			f(":scheme", req.URL.Scheme)
+		}
+		if trailers != "" {
+			f("trailer", trailers)
+		}
 
 
-	var didUA bool
-	for k, vv := range req.Header {
-		lowKey := strings.ToLower(k)
-		switch lowKey {
-		case "host", "content-length":
-			// Host is :authority, already sent.
-			// Content-Length is automatic, set below.
-			continue
-		case "connection", "proxy-connection", "transfer-encoding", "upgrade", "keep-alive":
-			// Per 8.1.2.2 Connection-Specific Header
-			// Fields, don't send connection-specific
-			// fields. We have already checked if any
-			// are error-worthy so just ignore the rest.
-			continue
-		case "user-agent":
-			// Match Go's http1 behavior: at most one
-			// User-Agent. If set to nil or empty string,
-			// then omit it. Otherwise if not mentioned,
-			// include the default (below).
-			didUA = true
-			if len(vv) < 1 {
+		var didUA bool
+		for k, vv := range req.Header {
+			if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") {
+				// Host is :authority, already sent.
+				// Content-Length is automatic, set below.
 				continue
 				continue
-			}
-			vv = vv[:1]
-			if vv[0] == "" {
+			} else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") ||
+				strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") ||
+				strings.EqualFold(k, "keep-alive") {
+				// Per 8.1.2.2 Connection-Specific Header
+				// Fields, don't send connection-specific
+				// fields. We have already checked if any
+				// are error-worthy so just ignore the rest.
 				continue
 				continue
+			} else if strings.EqualFold(k, "user-agent") {
+				// Match Go's http1 behavior: at most one
+				// User-Agent. If set to nil or empty string,
+				// then omit it. Otherwise if not mentioned,
+				// include the default (below).
+				didUA = true
+				if len(vv) < 1 {
+					continue
+				}
+				vv = vv[:1]
+				if vv[0] == "" {
+					continue
+				}
+
+			}
+
+			for _, v := range vv {
+				f(k, v)
 			}
 			}
 		}
 		}
-		for _, v := range vv {
-			cc.writeHeader(lowKey, v)
+		if shouldSendReqContentLength(req.Method, contentLength) {
+			f("content-length", strconv.FormatInt(contentLength, 10))
+		}
+		if addGzipHeader {
+			f("accept-encoding", "gzip")
+		}
+		if !didUA {
+			f("user-agent", defaultUserAgent)
 		}
 		}
 	}
 	}
-	if shouldSendReqContentLength(req.Method, contentLength) {
-		cc.writeHeader("content-length", strconv.FormatInt(contentLength, 10))
-	}
-	if addGzipHeader {
-		cc.writeHeader("accept-encoding", "gzip")
-	}
-	if !didUA {
-		cc.writeHeader("user-agent", defaultUserAgent)
+
+	// Do a first pass over the headers counting bytes to ensure
+	// we don't exceed cc.peerMaxHeaderListSize. This is done as a
+	// separate pass before encoding the headers to prevent
+	// modifying the hpack state.
+	hlSize := uint64(0)
+	enumerateHeaders(func(name, value string) {
+		hf := hpack.HeaderField{Name: name, Value: value}
+		hlSize += uint64(hf.Size())
+	})
+
+	if hlSize > cc.peerMaxHeaderListSize {
+		return nil, errRequestHeaderListSize
 	}
 	}
+
+	// Header list size is ok. Write the headers.
+	enumerateHeaders(func(name, value string) {
+		cc.writeHeader(strings.ToLower(name), value)
+	})
+
 	return cc.hbuf.Bytes(), nil
 	return cc.hbuf.Bytes(), nil
 }
 }
 
 
@@ -1188,17 +1302,29 @@ func shouldSendReqContentLength(method string, contentLength int64) bool {
 }
 }
 
 
 // requires cc.mu be held.
 // requires cc.mu be held.
-func (cc *ClientConn) encodeTrailers(req *http.Request) []byte {
+func (cc *ClientConn) encodeTrailers(req *http.Request) ([]byte, error) {
 	cc.hbuf.Reset()
 	cc.hbuf.Reset()
+
+	hlSize := uint64(0)
+	for k, vv := range req.Trailer {
+		for _, v := range vv {
+			hf := hpack.HeaderField{Name: k, Value: v}
+			hlSize += uint64(hf.Size())
+		}
+	}
+	if hlSize > cc.peerMaxHeaderListSize {
+		return nil, errRequestHeaderListSize
+	}
+
 	for k, vv := range req.Trailer {
 	for k, vv := range req.Trailer {
-		// Transfer-Encoding, etc.. have already been filter at the
+		// Transfer-Encoding, etc.. have already been filtered at the
 		// start of RoundTrip
 		// start of RoundTrip
 		lowKey := strings.ToLower(k)
 		lowKey := strings.ToLower(k)
 		for _, v := range vv {
 		for _, v := range vv {
 			cc.writeHeader(lowKey, v)
 			cc.writeHeader(lowKey, v)
 		}
 		}
 	}
 	}
-	return cc.hbuf.Bytes()
+	return cc.hbuf.Bytes(), nil
 }
 }
 
 
 func (cc *ClientConn) writeHeader(name, value string) {
 func (cc *ClientConn) writeHeader(name, value string) {
@@ -1246,7 +1372,9 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
 			cc.idleTimer.Reset(cc.idleTimeout)
 			cc.idleTimer.Reset(cc.idleTimeout)
 		}
 		}
 		close(cs.done)
 		close(cs.done)
-		cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
+		// Wake up checkResetOrDone via clientStream.awaitFlowControl and
+		// wake up RoundTrip if there is a pending request.
+		cc.cond.Broadcast()
 	}
 	}
 	return cs
 	return cs
 }
 }
@@ -1345,8 +1473,9 @@ func (rl *clientConnReadLoop) run() error {
 			cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
 			cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
 		}
 		}
 		if se, ok := err.(StreamError); ok {
 		if se, ok := err.(StreamError); ok {
-			if cs := cc.streamByID(se.StreamID, true /*ended; remove it*/); cs != nil {
+			if cs := cc.streamByID(se.StreamID, false); cs != nil {
 				cs.cc.writeStreamReset(cs.ID, se.Code, err)
 				cs.cc.writeStreamReset(cs.ID, se.Code, err)
+				cs.cc.forgetStreamID(cs.ID)
 				if se.Cause == nil {
 				if se.Cause == nil {
 					se.Cause = cc.fr.errDetail
 					se.Cause = cc.fr.errDetail
 				}
 				}
@@ -1407,7 +1536,17 @@ func (rl *clientConnReadLoop) run() error {
 
 
 func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
 func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
 	cc := rl.cc
 	cc := rl.cc
-	cs := cc.streamByID(f.StreamID, f.StreamEnded())
+	if f.StreamEnded() {
+		// Issue 20521: If the stream has ended, streamByID() causes
+		// clientStream.done to be closed, which causes the request's bodyWriter
+		// to be closed with an errStreamClosed, which may be received by
+		// clientConn.RoundTrip before the result of processing these headers.
+		// Deferring stream closure allows the header processing to occur first.
+		// clientConn.RoundTrip may still receive the bodyWriter error first, but
+		// the fix for issue 16102 prioritises any response.
+		defer cc.streamByID(f.StreamID, true)
+	}
+	cs := cc.streamByID(f.StreamID, false)
 	if cs == nil {
 	if cs == nil {
 		// We'd get here if we canceled a request while the
 		// We'd get here if we canceled a request while the
 		// server had its response still in flight. So if this
 		// server had its response still in flight. So if this
@@ -1668,6 +1807,7 @@ func (b transportResponseBody) Close() error {
 	}
 	}
 
 
 	cs.bufPipe.BreakWithError(errClosedResponseBody)
 	cs.bufPipe.BreakWithError(errClosedResponseBody)
+	cc.forgetStreamID(cs.ID)
 	return nil
 	return nil
 }
 }
 
 
@@ -1702,6 +1842,14 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
 		}
 		}
 		return nil
 		return nil
 	}
 	}
+	if !cs.firstByte {
+		cc.logf("protocol error: received DATA before a HEADERS frame")
+		rl.endStreamError(cs, StreamError{
+			StreamID: f.StreamID,
+			Code:     ErrCodeProtocol,
+		})
+		return nil
+	}
 	if f.Length > 0 {
 	if f.Length > 0 {
 		// Check connection-level flow control.
 		// Check connection-level flow control.
 		cc.mu.Lock()
 		cc.mu.Lock()
@@ -1713,16 +1861,27 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
 		}
 		}
 		// Return any padded flow control now, since we won't
 		// Return any padded flow control now, since we won't
 		// refund it later on body reads.
 		// refund it later on body reads.
-		if pad := int32(f.Length) - int32(len(data)); pad > 0 {
-			cs.inflow.add(pad)
-			cc.inflow.add(pad)
+		var refund int
+		if pad := int(f.Length) - len(data); pad > 0 {
+			refund += pad
+		}
+		// Return len(data) now if the stream is already closed,
+		// since data will never be read.
+		didReset := cs.didReset
+		if didReset {
+			refund += len(data)
+		}
+		if refund > 0 {
+			cc.inflow.add(int32(refund))
 			cc.wmu.Lock()
 			cc.wmu.Lock()
-			cc.fr.WriteWindowUpdate(0, uint32(pad))
-			cc.fr.WriteWindowUpdate(cs.ID, uint32(pad))
+			cc.fr.WriteWindowUpdate(0, uint32(refund))
+			if !didReset {
+				cs.inflow.add(int32(refund))
+				cc.fr.WriteWindowUpdate(cs.ID, uint32(refund))
+			}
 			cc.bw.Flush()
 			cc.bw.Flush()
 			cc.wmu.Unlock()
 			cc.wmu.Unlock()
 		}
 		}
-		didReset := cs.didReset
 		cc.mu.Unlock()
 		cc.mu.Unlock()
 
 
 		if len(data) > 0 && !didReset {
 		if len(data) > 0 && !didReset {
@@ -1805,6 +1964,8 @@ func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
 			cc.maxFrameSize = s.Val
 			cc.maxFrameSize = s.Val
 		case SettingMaxConcurrentStreams:
 		case SettingMaxConcurrentStreams:
 			cc.maxConcurrentStreams = s.Val
 			cc.maxConcurrentStreams = s.Val
+		case SettingMaxHeaderListSize:
+			cc.peerMaxHeaderListSize = uint64(s.Val)
 		case SettingInitialWindowSize:
 		case SettingInitialWindowSize:
 			// Values above the maximum flow-control
 			// Values above the maximum flow-control
 			// window size of 2^31-1 MUST be treated as a
 			// window size of 2^31-1 MUST be treated as a
@@ -1971,6 +2132,7 @@ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error)
 
 
 var (
 var (
 	errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
 	errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
+	errRequestHeaderListSize  = errors.New("http2: request header list larger than peer's advertised limit")
 	errPseudoTrailers         = errors.New("http2: invalid pseudo header in trailers")
 	errPseudoTrailers         = errors.New("http2: invalid pseudo header in trailers")
 )
 )
 
 

+ 1 - 6
vendor/golang.org/x/net/http2/write.go

@@ -10,7 +10,6 @@ import (
 	"log"
 	"log"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
-	"time"
 
 
 	"golang.org/x/net/http2/hpack"
 	"golang.org/x/net/http2/hpack"
 	"golang.org/x/net/lex/httplex"
 	"golang.org/x/net/lex/httplex"
@@ -90,11 +89,7 @@ type writeGoAway struct {
 
 
 func (p *writeGoAway) writeFrame(ctx writeContext) error {
 func (p *writeGoAway) writeFrame(ctx writeContext) error {
 	err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
 	err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
-	if p.code != 0 {
-		ctx.Flush() // ignore error: we're hanging up on them anyway
-		time.Sleep(50 * time.Millisecond)
-		ctx.CloseConn()
-	}
+	ctx.Flush() // ignore error: we're hanging up on them anyway
 	return err
 	return err
 }
 }
 
 

+ 39 - 27
vendor/golang.org/x/net/idna/idna.go

@@ -67,6 +67,15 @@ func VerifyDNSLength(verify bool) Option {
 	return func(o *options) { o.verifyDNSLength = verify }
 	return func(o *options) { o.verifyDNSLength = verify }
 }
 }
 
 
+// RemoveLeadingDots removes leading label separators. Leading runes that map to
+// dots, such as U+3002, are removed as well.
+//
+// This is the behavior suggested by the UTS #46 and is adopted by some
+// browsers.
+func RemoveLeadingDots(remove bool) Option {
+	return func(o *options) { o.removeLeadingDots = remove }
+}
+
 // ValidateLabels sets whether to check the mandatory label validation criteria
 // ValidateLabels sets whether to check the mandatory label validation criteria
 // as defined in Section 5.4 of RFC 5891. This includes testing for correct use
 // as defined in Section 5.4 of RFC 5891. This includes testing for correct use
 // of hyphens ('-'), normalization, validity of runes, and the context rules.
 // of hyphens ('-'), normalization, validity of runes, and the context rules.
@@ -133,14 +142,16 @@ func MapForLookup() Option {
 		o.mapping = validateAndMap
 		o.mapping = validateAndMap
 		StrictDomainName(true)(o)
 		StrictDomainName(true)(o)
 		ValidateLabels(true)(o)
 		ValidateLabels(true)(o)
+		RemoveLeadingDots(true)(o)
 	}
 	}
 }
 }
 
 
 type options struct {
 type options struct {
-	transitional    bool
-	useSTD3Rules    bool
-	validateLabels  bool
-	verifyDNSLength bool
+	transitional      bool
+	useSTD3Rules      bool
+	validateLabels    bool
+	verifyDNSLength   bool
+	removeLeadingDots bool
 
 
 	trie *idnaTrie
 	trie *idnaTrie
 
 
@@ -156,7 +167,7 @@ type options struct {
 	bidirule func(s string) bool
 	bidirule func(s string) bool
 }
 }
 
 
-// A Profile defines the configuration of a IDNA mapper.
+// A Profile defines the configuration of an IDNA mapper.
 type Profile struct {
 type Profile struct {
 	options
 	options
 }
 }
@@ -240,21 +251,23 @@ var (
 
 
 	punycode = &Profile{}
 	punycode = &Profile{}
 	lookup   = &Profile{options{
 	lookup   = &Profile{options{
-		transitional:   true,
-		useSTD3Rules:   true,
-		validateLabels: true,
-		trie:           trie,
-		fromPuny:       validateFromPunycode,
-		mapping:        validateAndMap,
-		bidirule:       bidirule.ValidString,
+		transitional:      true,
+		useSTD3Rules:      true,
+		validateLabels:    true,
+		removeLeadingDots: true,
+		trie:              trie,
+		fromPuny:          validateFromPunycode,
+		mapping:           validateAndMap,
+		bidirule:          bidirule.ValidString,
 	}}
 	}}
 	display = &Profile{options{
 	display = &Profile{options{
-		useSTD3Rules:   true,
-		validateLabels: true,
-		trie:           trie,
-		fromPuny:       validateFromPunycode,
-		mapping:        validateAndMap,
-		bidirule:       bidirule.ValidString,
+		useSTD3Rules:      true,
+		validateLabels:    true,
+		removeLeadingDots: true,
+		trie:              trie,
+		fromPuny:          validateFromPunycode,
+		mapping:           validateAndMap,
+		bidirule:          bidirule.ValidString,
 	}}
 	}}
 	registration = &Profile{options{
 	registration = &Profile{options{
 		useSTD3Rules:    true,
 		useSTD3Rules:    true,
@@ -293,7 +306,9 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
 		s, err = p.mapping(p, s)
 		s, err = p.mapping(p, s)
 	}
 	}
 	// Remove leading empty labels.
 	// Remove leading empty labels.
-	for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
+	if p.removeLeadingDots {
+		for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
+		}
 	}
 	}
 	// It seems like we should only create this error on ToASCII, but the
 	// It seems like we should only create this error on ToASCII, but the
 	// UTS 46 conformance tests suggests we should always check this.
 	// UTS 46 conformance tests suggests we should always check this.
@@ -373,23 +388,20 @@ func validateRegistration(p *Profile, s string) (string, error) {
 	if !norm.NFC.IsNormalString(s) {
 	if !norm.NFC.IsNormalString(s) {
 		return s, &labelError{s, "V1"}
 		return s, &labelError{s, "V1"}
 	}
 	}
-	var err error
 	for i := 0; i < len(s); {
 	for i := 0; i < len(s); {
 		v, sz := trie.lookupString(s[i:])
 		v, sz := trie.lookupString(s[i:])
-		i += sz
 		// Copy bytes not copied so far.
 		// Copy bytes not copied so far.
 		switch p.simplify(info(v).category()) {
 		switch p.simplify(info(v).category()) {
 		// TODO: handle the NV8 defined in the Unicode idna data set to allow
 		// TODO: handle the NV8 defined in the Unicode idna data set to allow
 		// for strict conformance to IDNA2008.
 		// for strict conformance to IDNA2008.
 		case valid, deviation:
 		case valid, deviation:
 		case disallowed, mapped, unknown, ignored:
 		case disallowed, mapped, unknown, ignored:
-			if err == nil {
-				r, _ := utf8.DecodeRuneInString(s[i:])
-				err = runeError(r)
-			}
+			r, _ := utf8.DecodeRuneInString(s[i:])
+			return s, runeError(r)
 		}
 		}
+		i += sz
 	}
 	}
-	return s, err
+	return s, nil
 }
 }
 
 
 func validateAndMap(p *Profile, s string) (string, error) {
 func validateAndMap(p *Profile, s string) (string, error) {
@@ -408,7 +420,7 @@ func validateAndMap(p *Profile, s string) (string, error) {
 			continue
 			continue
 		case disallowed:
 		case disallowed:
 			if err == nil {
 			if err == nil {
-				r, _ := utf8.DecodeRuneInString(s[i:])
+				r, _ := utf8.DecodeRuneInString(s[start:])
 				err = runeError(r)
 				err = runeError(r)
 			}
 			}
 			continue
 			continue

+ 4 - 4
vendor/golang.org/x/net/proxy/per_host.go

@@ -9,7 +9,7 @@ import (
 	"strings"
 	"strings"
 )
 )
 
 
-// A PerHost directs connections to a default Dialer unless the hostname
+// A PerHost directs connections to a default Dialer unless the host name
 // requested matches one of a number of exceptions.
 // requested matches one of a number of exceptions.
 type PerHost struct {
 type PerHost struct {
 	def, bypass Dialer
 	def, bypass Dialer
@@ -61,7 +61,7 @@ func (p *PerHost) dialerForRequest(host string) Dialer {
 			return p.bypass
 			return p.bypass
 		}
 		}
 		if host == zone[1:] {
 		if host == zone[1:] {
-			// For a zone "example.com", we match "example.com"
+			// For a zone ".example.com", we match "example.com"
 			// too.
 			// too.
 			return p.bypass
 			return p.bypass
 		}
 		}
@@ -76,7 +76,7 @@ func (p *PerHost) dialerForRequest(host string) Dialer {
 
 
 // AddFromString parses a string that contains comma-separated values
 // AddFromString parses a string that contains comma-separated values
 // specifying hosts that should use the bypass proxy. Each value is either an
 // specifying hosts that should use the bypass proxy. Each value is either an
-// IP address, a CIDR range, a zone (*.example.com) or a hostname
+// IP address, a CIDR range, a zone (*.example.com) or a host name
 // (localhost). A best effort is made to parse the string and errors are
 // (localhost). A best effort is made to parse the string and errors are
 // ignored.
 // ignored.
 func (p *PerHost) AddFromString(s string) {
 func (p *PerHost) AddFromString(s string) {
@@ -131,7 +131,7 @@ func (p *PerHost) AddZone(zone string) {
 	p.bypassZones = append(p.bypassZones, zone)
 	p.bypassZones = append(p.bypassZones, zone)
 }
 }
 
 
-// AddHost specifies a hostname that will use the bypass proxy.
+// AddHost specifies a host name that will use the bypass proxy.
 func (p *PerHost) AddHost(host string) {
 func (p *PerHost) AddHost(host string) {
 	if strings.HasSuffix(host, ".") {
 	if strings.HasSuffix(host, ".") {
 		host = host[:len(host)-1]
 		host = host[:len(host)-1]

+ 42 - 2
vendor/golang.org/x/net/proxy/proxy.go

@@ -11,6 +11,7 @@ import (
 	"net"
 	"net"
 	"net/url"
 	"net/url"
 	"os"
 	"os"
+	"sync"
 )
 )
 
 
 // A Dialer is a means to establish a connection.
 // A Dialer is a means to establish a connection.
@@ -27,7 +28,7 @@ type Auth struct {
 // FromEnvironment returns the dialer specified by the proxy related variables in
 // FromEnvironment returns the dialer specified by the proxy related variables in
 // the environment.
 // the environment.
 func FromEnvironment() Dialer {
 func FromEnvironment() Dialer {
-	allProxy := os.Getenv("all_proxy")
+	allProxy := allProxyEnv.Get()
 	if len(allProxy) == 0 {
 	if len(allProxy) == 0 {
 		return Direct
 		return Direct
 	}
 	}
@@ -41,7 +42,7 @@ func FromEnvironment() Dialer {
 		return Direct
 		return Direct
 	}
 	}
 
 
-	noProxy := os.Getenv("no_proxy")
+	noProxy := noProxyEnv.Get()
 	if len(noProxy) == 0 {
 	if len(noProxy) == 0 {
 		return proxy
 		return proxy
 	}
 	}
@@ -92,3 +93,42 @@ func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
 
 
 	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
 	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
 }
 }
+
+var (
+	allProxyEnv = &envOnce{
+		names: []string{"ALL_PROXY", "all_proxy"},
+	}
+	noProxyEnv = &envOnce{
+		names: []string{"NO_PROXY", "no_proxy"},
+	}
+)
+
+// envOnce looks up an environment variable (optionally by multiple
+// names) once. It mitigates expensive lookups on some platforms
+// (e.g. Windows).
+// (Borrowed from net/http/transport.go)
+type envOnce struct {
+	names []string
+	once  sync.Once
+	val   string
+}
+
+func (e *envOnce) Get() string {
+	e.once.Do(e.init)
+	return e.val
+}
+
+func (e *envOnce) init() {
+	for _, n := range e.names {
+		e.val = os.Getenv(n)
+		if e.val != "" {
+			return
+		}
+	}
+}
+
+// reset is used by tests
+func (e *envOnce) reset() {
+	e.once = sync.Once{}
+	e.val = ""
+}

+ 4 - 3
vendor/golang.org/x/net/proxy/socks5.go

@@ -12,7 +12,7 @@ import (
 )
 )
 
 
 // SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
 // SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
-// with an optional username and password. See RFC 1928.
+// with an optional username and password. See RFC 1928 and RFC 1929.
 func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) {
 func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) {
 	s := &socks5{
 	s := &socks5{
 		network: network,
 		network: network,
@@ -60,7 +60,7 @@ var socks5Errors = []string{
 	"address type not supported",
 	"address type not supported",
 }
 }
 
 
-// Dial connects to the address addr on the network net via the SOCKS5 proxy.
+// Dial connects to the address addr on the given network via the SOCKS5 proxy.
 func (s *socks5) Dial(network, addr string) (net.Conn, error) {
 func (s *socks5) Dial(network, addr string) (net.Conn, error) {
 	switch network {
 	switch network {
 	case "tcp", "tcp6", "tcp4":
 	case "tcp", "tcp6", "tcp4":
@@ -120,6 +120,7 @@ func (s *socks5) connect(conn net.Conn, target string) error {
 		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
 		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
 	}
 	}
 
 
+	// See RFC 1929
 	if buf[1] == socks5AuthPassword {
 	if buf[1] == socks5AuthPassword {
 		buf = buf[:0]
 		buf = buf[:0]
 		buf = append(buf, 1 /* password protocol version */)
 		buf = append(buf, 1 /* password protocol version */)
@@ -154,7 +155,7 @@ func (s *socks5) connect(conn net.Conn, target string) error {
 		buf = append(buf, ip...)
 		buf = append(buf, ip...)
 	} else {
 	} else {
 		if len(host) > 255 {
 		if len(host) > 255 {
-			return errors.New("proxy: destination hostname too long: " + host)
+			return errors.New("proxy: destination host name too long: " + host)
 		}
 		}
 		buf = append(buf, socks5Domain)
 		buf = append(buf, socks5Domain)
 		buf = append(buf, byte(len(host)))
 		buf = append(buf, byte(len(host)))

+ 3 - 3
vendor/golang.org/x/net/trace/events.go

@@ -39,9 +39,9 @@ var buckets = []bucket{
 }
 }
 
 
 // RenderEvents renders the HTML page typically served at /debug/events.
 // RenderEvents renders the HTML page typically served at /debug/events.
-// It does not do any auth checking; see AuthRequest for the default auth check
-// used by the handler registered on http.DefaultServeMux.
-// req may be nil.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Events handler.
 func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
 func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
 	now := time.Now()
 	now := time.Now()
 	data := &struct {
 	data := &struct {

+ 37 - 21
vendor/golang.org/x/net/trace/trace.go

@@ -110,30 +110,46 @@ var AuthRequest = func(req *http.Request) (any, sensitive bool) {
 }
 }
 
 
 func init() {
 func init() {
-	http.HandleFunc("/debug/requests", func(w http.ResponseWriter, req *http.Request) {
-		any, sensitive := AuthRequest(req)
-		if !any {
-			http.Error(w, "not allowed", http.StatusUnauthorized)
-			return
-		}
-		w.Header().Set("Content-Type", "text/html; charset=utf-8")
-		Render(w, req, sensitive)
-	})
-	http.HandleFunc("/debug/events", func(w http.ResponseWriter, req *http.Request) {
-		any, sensitive := AuthRequest(req)
-		if !any {
-			http.Error(w, "not allowed", http.StatusUnauthorized)
-			return
-		}
-		w.Header().Set("Content-Type", "text/html; charset=utf-8")
-		RenderEvents(w, req, sensitive)
-	})
+	// TODO(jbd): Serve Traces from /debug/traces in the future?
+	// There is no requirement for a request to be present to have traces.
+	http.HandleFunc("/debug/requests", Traces)
+	http.HandleFunc("/debug/events", Events)
+}
+
+// Traces responds with traces from the program.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/requests.
+//
+// It performs authorization by running AuthRequest.
+func Traces(w http.ResponseWriter, req *http.Request) {
+	any, sensitive := AuthRequest(req)
+	if !any {
+		http.Error(w, "not allowed", http.StatusUnauthorized)
+		return
+	}
+	w.Header().Set("Content-Type", "text/html; charset=utf-8")
+	Render(w, req, sensitive)
+}
+
+// Events responds with a page of events collected by EventLogs.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/events.
+//
+// It performs authorization by running AuthRequest.
+func Events(w http.ResponseWriter, req *http.Request) {
+	any, sensitive := AuthRequest(req)
+	if !any {
+		http.Error(w, "not allowed", http.StatusUnauthorized)
+		return
+	}
+	w.Header().Set("Content-Type", "text/html; charset=utf-8")
+	RenderEvents(w, req, sensitive)
 }
 }
 
 
 // Render renders the HTML page typically served at /debug/requests.
 // Render renders the HTML page typically served at /debug/requests.
-// It does not do any auth checking; see AuthRequest for the default auth check
-// used by the handler registered on http.DefaultServeMux.
-// req may be nil.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Traces handler.
 func Render(w io.Writer, req *http.Request, sensitive bool) {
 func Render(w io.Writer, req *http.Request, sensitive bool) {
 	data := &struct {
 	data := &struct {
 		Families         []string
 		Families         []string