Browse Source

http2: minor transport code & docs cleanups

Change-Id: Ieb02b751f3a0c1100e5201e7617ad9f055baf28e
Reviewed-on: https://go-review.googlesource.com/16820
Reviewed-by: Andrew Gerrand <adg@golang.org>
Brad Fitzpatrick 10 years ago
parent
commit
cf8d7ec53c
1 changed files with 17 additions and 9 deletions
  1. 17 9
      http2/transport.go

+ 17 - 9
http2/transport.go

@@ -198,7 +198,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
 			return nil, err
 		}
 		res, err := cc.RoundTrip(req)
-		if shouldRetryRequest(err) { // TODO: or clientconn is overloaded (too many outstanding requests)?
+		if shouldRetryRequest(req, err) {
 			continue
 		}
 		if err != nil {
@@ -217,11 +217,15 @@ func (t *Transport) CloseIdleConnections() {
 	}
 }
 
-var errClientConnClosed = errors.New("http2: client conn is closed")
+var (
+	errClientConnClosed   = errors.New("http2: client conn is closed")
+	errClientConnUnusable = errors.New("http2: client conn not usable")
+)
 
-func shouldRetryRequest(err error) bool {
-	// TODO: or GOAWAY graceful shutdown stuff
-	return err == errClientConnClosed
+func shouldRetryRequest(req *http.Request, err error) bool {
+	// TODO: retry GET requests (no bodies) more aggressively, if shutdown
+	// before response.
+	return err == errClientConnUnusable
 }
 
 func (t *Transport) dialClientConn(addr string) (*ClientConn, error) {
@@ -360,6 +364,10 @@ func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
 func (cc *ClientConn) CanTakeNewRequest() bool {
 	cc.mu.Lock()
 	defer cc.mu.Unlock()
+	return cc.canTakeNewRequestLocked()
+}
+
+func (cc *ClientConn) canTakeNewRequestLocked() bool {
 	return cc.goAway == nil &&
 		int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
 		cc.nextStreamID < 2147483647
@@ -421,17 +429,17 @@ func (cc *ClientConn) putFrameScratchBuffer(buf []byte) {
 func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
 	cc.mu.Lock()
 
-	if cc.closed {
+	if cc.closed || !cc.canTakeNewRequestLocked() {
 		cc.mu.Unlock()
-		return nil, errClientConnClosed
+		return nil, errClientConnUnusable
 	}
 
 	cs := cc.newStream()
 	hasBody := req.Body != nil
 
-	// we send: HEADERS[+CONTINUATION] + (DATA?)
+	// we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,}
 	hdrs := cc.encodeHeaders(req)
-	first := true
+	first := true // first frame written (HEADERS is first, then CONTINUATION)
 
 	cc.wmu.Lock()
 	frameSize := int(cc.maxFrameSize)