1
0
mirror of https://github.com/golang/go synced 2024-11-19 21:04:43 -07:00

net/http: update bundled http2, fixes TestConcurrentReadWriteReqBody_h2

Updates http2 to x/net git rev 520af5de654d for
https://golang.org/cl/18370

Fixes #13659

Change-Id: I920eaff6036ac22c500a97449826c6b12f873d7f
Reviewed-on: https://go-review.googlesource.com/18371
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
Brad Fitzpatrick 2016-01-07 04:59:25 +00:00
parent 002e658a91
commit 305b4baf41
2 changed files with 31 additions and 26 deletions

View File

@ -622,10 +622,7 @@ func testResponseBodyReadAfterClose(t *testing.T, h2 bool) {
} }
func TestConcurrentReadWriteReqBody_h1(t *testing.T) { testConcurrentReadWriteReqBody(t, h1Mode) } func TestConcurrentReadWriteReqBody_h1(t *testing.T) { testConcurrentReadWriteReqBody(t, h1Mode) }
func TestConcurrentReadWriteReqBody_h2(t *testing.T) { func TestConcurrentReadWriteReqBody_h2(t *testing.T) { testConcurrentReadWriteReqBody(t, h2Mode) }
t.Skip("known failing; golang.org/issue/13659")
testConcurrentReadWriteReqBody(t, h2Mode)
}
func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) { func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) {
defer afterTest(t) defer afterTest(t)
const reqBody = "some request body" const reqBody = "some request body"
@ -653,7 +650,7 @@ func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) {
// our HTTP/1 implementation intentionally // our HTTP/1 implementation intentionally
// doesn't permit writes during read (mostly // doesn't permit writes during read (mostly
// due to it being undefined); if that is ever // due to it being undefined); if that is ever
// relaxed, fix this. // relaxed, change this.
<-didRead <-didRead
} }
io.WriteString(w, resBody) io.WriteString(w, resBody)

View File

@ -1406,10 +1406,6 @@ func http2parseContinuationFrame(fh http2FrameHeader, p []byte) (http2Frame, err
return &http2ContinuationFrame{fh, p}, nil return &http2ContinuationFrame{fh, p}, nil
} }
func (f *http2ContinuationFrame) StreamEnded() bool {
return f.http2FrameHeader.Flags.Has(http2FlagDataEndStream)
}
func (f *http2ContinuationFrame) HeaderBlockFragment() []byte { func (f *http2ContinuationFrame) HeaderBlockFragment() []byte {
f.checkValid() f.checkValid()
return f.headerFragBuf return f.headerFragBuf
@ -4222,8 +4218,8 @@ type http2clientStream struct {
done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
// owned by clientConnReadLoop: // owned by clientConnReadLoop:
headersDone bool // got HEADERS w/ END_HEADERS pastHeaders bool // got HEADERS w/ END_HEADERS
trailersDone bool // got second HEADERS frame w/ END_HEADERS pastTrailers bool // got second HEADERS frame w/ END_HEADERS
trailer Header // accumulated trailers trailer Header // accumulated trailers
resTrailer Header // client's Response.Trailer resTrailer Header // client's Response.Trailer
@ -4923,9 +4919,10 @@ type http2clientConnReadLoop struct {
hdec *hpack.Decoder hdec *hpack.Decoder
// Fields reset on each HEADERS: // Fields reset on each HEADERS:
nextRes *Response nextRes *Response
sawRegHeader bool // saw non-pseudo header sawRegHeader bool // saw non-pseudo header
reqMalformed error // non-nil once known to be malformed reqMalformed error // non-nil once known to be malformed
lastHeaderEndsStream bool
} }
// readLoop runs in its own goroutine and reads and dispatches frames. // readLoop runs in its own goroutine and reads and dispatches frames.
@ -5018,26 +5015,28 @@ func (rl *http2clientConnReadLoop) run() error {
func (rl *http2clientConnReadLoop) processHeaders(f *http2HeadersFrame) error { func (rl *http2clientConnReadLoop) processHeaders(f *http2HeadersFrame) error {
rl.sawRegHeader = false rl.sawRegHeader = false
rl.reqMalformed = nil rl.reqMalformed = nil
rl.lastHeaderEndsStream = f.StreamEnded()
rl.nextRes = &Response{ rl.nextRes = &Response{
Proto: "HTTP/2.0", Proto: "HTTP/2.0",
ProtoMajor: 2, ProtoMajor: 2,
Header: make(Header), Header: make(Header),
} }
return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded(), f.StreamEnded()) return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded())
} }
func (rl *http2clientConnReadLoop) processContinuation(f *http2ContinuationFrame) error { func (rl *http2clientConnReadLoop) processContinuation(f *http2ContinuationFrame) error {
return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded(), f.StreamEnded()) return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded())
} }
func (rl *http2clientConnReadLoop) processHeaderBlockFragment(frag []byte, streamID uint32, headersEnded, streamEnded bool) error { func (rl *http2clientConnReadLoop) processHeaderBlockFragment(frag []byte, streamID uint32, finalFrag bool) error {
cc := rl.cc cc := rl.cc
cs := cc.streamByID(streamID, streamEnded) streamEnded := rl.lastHeaderEndsStream
cs := cc.streamByID(streamID, streamEnded && finalFrag)
if cs == nil { if cs == nil {
return nil return nil
} }
if cs.headersDone { if cs.pastHeaders {
rl.hdec.SetEmitFunc(cs.onNewTrailerField) rl.hdec.SetEmitFunc(cs.onNewTrailerField)
} else { } else {
rl.hdec.SetEmitFunc(rl.onNewHeaderField) rl.hdec.SetEmitFunc(rl.onNewHeaderField)
@ -5046,22 +5045,25 @@ func (rl *http2clientConnReadLoop) processHeaderBlockFragment(frag []byte, strea
if err != nil { if err != nil {
return http2ConnectionError(http2ErrCodeCompression) return http2ConnectionError(http2ErrCodeCompression)
} }
if err := rl.hdec.Close(); err != nil { if finalFrag {
return http2ConnectionError(http2ErrCodeCompression) if err := rl.hdec.Close(); err != nil {
return http2ConnectionError(http2ErrCodeCompression)
}
} }
if !headersEnded {
if !finalFrag {
return nil return nil
} }
if !cs.headersDone { if !cs.pastHeaders {
cs.headersDone = true cs.pastHeaders = true
} else { } else {
if cs.trailersDone { if cs.pastTrailers {
return http2ConnectionError(http2ErrCodeProtocol) return http2ConnectionError(http2ErrCodeProtocol)
} }
cs.trailersDone = true cs.pastTrailers = true
if !streamEnded { if !streamEnded {
return http2ConnectionError(http2ErrCodeProtocol) return http2ConnectionError(http2ErrCodeProtocol)
@ -5078,6 +5080,12 @@ func (rl *http2clientConnReadLoop) processHeaderBlockFragment(frag []byte, strea
res := rl.nextRes res := rl.nextRes
if res.StatusCode == 100 {
cs.pastHeaders = false
return nil
}
if !streamEnded || cs.req.Method == "HEAD" { if !streamEnded || cs.req.Method == "HEAD" {
res.ContentLength = -1 res.ContentLength = -1
if clens := res.Header["Content-Length"]; len(clens) == 1 { if clens := res.Header["Content-Length"]; len(clens) == 1 {