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:
parent
002e658a91
commit
305b4baf41
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user