Skip to content

Commit 96dbb96

Browse files
committed
http2: make Transport use Request.Context, set Response.Uncompressed
Go 1.7 introduces Request.Context and Response.Uncompressed. Use them both in the http2 Transport when building for Go 1.7. Tests are in the main repo. Updates golang/go#15366 Updates golang/go#15134 Change-Id: I4b78a2710b6cf30c769c7f85cea15ecde653a317 Reviewed-on: https://go-review.googlesource.com/23002 Reviewed-by: Andrew Gerrand <adg@golang.org>
1 parent 2a35e68 commit 96dbb96

File tree

3 files changed

+60
-8
lines changed

3 files changed

+60
-8
lines changed

http2/go17.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build go1.7
6+
7+
package http2
8+
9+
import (
10+
"context"
11+
"net/http"
12+
)
13+
14+
func reqContext(r *http.Request) context.Context { return r.Context() }
15+
16+
func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }

http2/not_go17.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build !go1.7
6+
7+
package http2
8+
9+
import "net/http"
10+
11+
type fakeContext struct{}
12+
13+
func (fakeContext) Done() <-chan struct{} { return nil }
14+
func (fakeContext) Err() error { panic("should not be called") }
15+
16+
func reqContext(r *http.Request) fakeContext {
17+
return fakeContext{}
18+
}
19+
20+
func setResponseUncompressed(res *http.Response) {
21+
// Nothing.
22+
}

http2/transport.go

+22-8
Original file line numberDiff line numberDiff line change
@@ -195,18 +195,22 @@ type clientStream struct {
195195
}
196196

197197
// awaitRequestCancel runs in its own goroutine and waits for the user
198-
// to either cancel a RoundTrip request (using the provided
199-
// Request.Cancel channel), or for the request to be done (any way it
200-
// might be removed from the cc.streams map: peer reset, successful
201-
// completion, TCP connection breakage, etc)
202-
func (cs *clientStream) awaitRequestCancel(cancel <-chan struct{}) {
203-
if cancel == nil {
198+
// to cancel a RoundTrip request, its context to expire, or for the
199+
// request to be done (any way it might be removed from the cc.streams
200+
// map: peer reset, successful completion, TCP connection breakage,
201+
// etc)
202+
func (cs *clientStream) awaitRequestCancel(req *http.Request) {
203+
ctx := reqContext(req)
204+
if req.Cancel == nil && ctx.Done() == nil {
204205
return
205206
}
206207
select {
207-
case <-cancel:
208+
case <-req.Cancel:
208209
cs.bufPipe.CloseWithError(errRequestCanceled)
209210
cs.cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
211+
case <-ctx.Done():
212+
cs.bufPipe.CloseWithError(ctx.Err())
213+
cs.cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
210214
case <-cs.done:
211215
}
212216
}
@@ -684,6 +688,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
684688

685689
readLoopResCh := cs.resc
686690
bodyWritten := false
691+
ctx := reqContext(req)
687692

688693
for {
689694
select {
@@ -716,6 +721,14 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
716721
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
717722
}
718723
return nil, errTimeout
724+
case <-ctx.Done():
725+
cc.forgetStreamID(cs.ID)
726+
if !hasBody || bodyWritten {
727+
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
728+
} else {
729+
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
730+
}
731+
return nil, ctx.Err()
719732
case <-req.Cancel:
720733
cc.forgetStreamID(cs.ID)
721734
if !hasBody || bodyWritten {
@@ -1284,13 +1297,14 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
12841297
cs.bufPipe = pipe{b: buf}
12851298
cs.bytesRemain = res.ContentLength
12861299
res.Body = transportResponseBody{cs}
1287-
go cs.awaitRequestCancel(cs.req.Cancel)
1300+
go cs.awaitRequestCancel(cs.req)
12881301

12891302
if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" {
12901303
res.Header.Del("Content-Encoding")
12911304
res.Header.Del("Content-Length")
12921305
res.ContentLength = -1
12931306
res.Body = &gzipReader{body: res.Body}
1307+
setResponseUncompressed(res)
12941308
}
12951309
return res, nil
12961310
}

0 commit comments

Comments
 (0)