func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*http.Request, error) {
	if !canRetryError(err) {
		return nil, err
	}
	if req.Body == nil || reqBodyIsNoBody(req.Body) {
		return req, nil
	}
	getBody := reqGetBody(req)  
	if getBody != nil {
		body, err := getBody()
		if err != nil {
			return nil, err
		}
		newReq := *req
		newReq.Body = body
		return &newReq, nil
	}
	if !afterBodyWrite {
		return req, nil
	}
	return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
}
shouldRetryRequest is called by RoundTrip when a request fails to get
response headers. It is always called with a non-nil error.
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.
package http2
import (
	"bufio"
	"bytes"
	"compress/gzip"
	"crypto/rand"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math"
	mathrand "math/rand"
	"net"
	"net/http"
	"net/textproto"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
	"golang.org/x/net/http/httpguts"
	"golang.org/x/net/http2/hpack"
	"golang.org/x/net/idna"
)
const (
	transportDefaultConnFlow = 1 << 30
	transportDefaultStreamFlow = 4 << 20
	transportDefaultStreamMinRefresh = 4 << 10
	defaultUserAgent = "Go-http-client/2.0"
)
type Transport struct {
	DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
	TLSClientConfig *tls.Config
	ConnPool ClientConnPool
	DisableCompression bool
	AllowHTTP bool
	MaxHeaderListSize uint32
	t1 *http.Transport
	connPoolOnce  sync.Once
	connPoolOrDef ClientConnPool  
}
func (t *Transport) maxHeaderListSize() uint32 {
	if t.MaxHeaderListSize == 0 {
		return 10 << 20
	}
	if t.MaxHeaderListSize == 0xffffffff {
		return 0
	}
	return t.MaxHeaderListSize
}
func (t *Transport) disableCompression() bool {
	return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
}
var errTransportVersion = errors.New("http2: ConfigureTransport is only supported starting at Go 1.6")
func ConfigureTransport(t1 *http.Transport) error {
	_, err := configureTransport(t1)  
	return err
}
func (t *Transport) connPool() ClientConnPool {
	t.connPoolOnce.Do(t.initConnPool)
	return t.connPoolOrDef
}
func (t *Transport) initConnPool() {
	if t.ConnPool != nil {
		t.connPoolOrDef = t.ConnPool
	} else {
		t.connPoolOrDef = &clientConnPool{t: t}
	}
}
type ClientConn struct {
	t         *Transport
	tconn     net.Conn              
	tlsState  *tls.ConnectionState  
	singleUse bool                  
	readerDone chan struct{}  
	readerErr  error          
	idleTimeout time.Duration  
	idleTimer   *time.Timer
	mu              sync.Mutex  
	cond            *sync.Cond  
	flow            flow        
	inflow          flow        
	closing         bool
	closed          bool
	wantSettingsAck bool                      
	goAway          *GoAwayFrame              
	goAwayDebug     string                    
	streams         map[uint32]*clientStream  
	nextStreamID    uint32
	pendingRequests int                        
	pings           map[[8]byte]chan struct{}  
	bw              *bufio.Writer
	br              *bufio.Reader
	fr              *Framer
	lastActive      time.Time
	maxFrameSize          uint32
	maxConcurrentStreams  uint32
	peerMaxHeaderListSize uint64
	initialWindowSize     uint32
	hbuf    bytes.Buffer  
	henc    *hpack.Encoder
	freeBuf [][]byte
	wmu  sync.Mutex  
	werr error       
}
type clientStream struct {
	cc            *ClientConn
	req           *http.Request
	trace         *clientTrace  
	ID            uint32
	resc          chan resAndError
	bufPipe       pipe  
	startedWrite  bool  
	requestedGzip bool
	on100         func()  
	flow        flow   
	inflow      flow   
	bytesRemain int64  
	readErr     error  
	stopReqBody error  
	didReset    bool   
	peerReset chan struct{}  
	resetErr  error          
	done chan struct{}  
	firstByte    bool   
	pastHeaders  bool   
	pastTrailers bool   
	num1xx       uint8  
	trailer    http.Header   
	resTrailer *http.Header  
}
func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
	ctx := reqContext(req)
	if req.Cancel == nil && ctx.Done() == nil {
		return nil
	}
	select {
	case <-req.Cancel:
		return errRequestCanceled
	case <-ctx.Done():
		return ctx.Err()
	case <-done:
		return nil
	}
}
var got1xxFuncForTests func(int, textproto.MIMEHeader) error
func (cs *clientStream) get1xxTraceFunc() func(int, textproto.MIMEHeader) error {
	if fn := got1xxFuncForTests; fn != nil {
		return fn
	}
	return traceGot1xxResponseFunc(cs.trace)
}
func (cs *clientStream) awaitRequestCancel(req *http.Request) {
	if err := awaitRequestCancel(req, cs.done); err != nil {
		cs.cancelStream()
		cs.bufPipe.CloseWithError(err)
	}
}
func (cs *clientStream) cancelStream() {
	cc := cs.cc
	cc.mu.Lock()
	didReset := cs.didReset
	cs.didReset = true
	cc.mu.Unlock()
	if !didReset {
		cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
		cc.forgetStreamID(cs.ID)
	}
}
func (cs *clientStream) checkResetOrDone() error {
	select {
	case <-cs.peerReset:
		return cs.resetErr
	case <-cs.done:
		return errStreamClosed
	default:
		return nil
	}
}
func (cs *clientStream) getStartedWrite() bool {
	cc := cs.cc
	cc.mu.Lock()
	defer cc.mu.Unlock()
	return cs.startedWrite
}
func (cs *clientStream) abortRequestBodyWrite(err error) {
	if err == nil {
		panic("nil error")
	}
	cc := cs.cc
	cc.mu.Lock()
	cs.stopReqBody = err
	cc.cond.Broadcast()
	cc.mu.Unlock()
}
type stickyErrWriter struct {
	w   io.Writer
	err *error
}
func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
	if *sew.err != nil {
		return 0, *sew.err
	}
	n, err = sew.w.Write(p)
	*sew.err = err
	return
}
type noCachedConnError struct{}
func (noCachedConnError) IsHTTP2NoCachedConnError() {}
func (noCachedConnError) Error() string             { return "http2: no cached connection was available" }
func isNoCachedConnError(err error) bool {
	_, ok := err.(interface{ IsHTTP2NoCachedConnError() })
	return ok
}
var ErrNoCachedConn error = noCachedConnError{}
type RoundTripOpt struct {
	OnlyCachedConn bool
}
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
	return t.RoundTripOpt(req, RoundTripOpt{})
}
func authorityAddr(scheme string, authority string) (addr string) {
	host, port, err := net.SplitHostPort(authority)
	if err != nil {  
		port = "443"
		if scheme == "http" {
			port = "80"
		}
		host = authority
	}
	if a, err := idna.ToASCII(host); err == nil {
		host = a
	}
	if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
		return host + ":" + port
	}
	return net.JoinHostPort(host, port)
}
func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
	if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
		return nil, errors.New("http2: unsupported scheme")
	}
	addr := authorityAddr(req.URL.Scheme, req.URL.Host)
	for retry := 0; ; retry++ {
		cc, err := t.connPool().GetClientConn(req, addr)
		if err != nil {
			t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
			return nil, err
		}
		traceGotConn(req, cc)
		res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
		if err != nil && retry <= 6 {
			if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
				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 {
			t.vlogf("RoundTrip failure: %v", err)
			return nil, err
		}
		return res, nil
	}
}
func (t *Transport) CloseIdleConnections() {
	if cp, ok := t.connPool().(clientConnPoolIdleCloser); ok {
		cp.closeIdleConnections()
	}
}
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")
)