From 0d3143ea781298172cd432b637e8b8f0b0526951 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 25 Apr 2017 20:36:07 +0000 Subject: [PATCH] net/http: update bundled x/net/http2 This updates the bundled http2 package from git rev 5602c733f70afc6dcec6766be0d5034d4c4f14de of the x/net repo for: http2: Use NO_ERROR instead of CANCEL when responding before the request is finished https://golang.org/cl/40630 http2: enforce write deadline per stream https://golang.org/cl/34727 Updates golang/go#19948 Fixes golang/go#18437 Change-Id: I14500476e91551fa8f27a1aeb8ae3cac9600b74c Reviewed-on: https://go-review.googlesource.com/41753 Reviewed-by: Kale Blankenship Reviewed-by: Tom Bergan Run-TryBot: Kale Blankenship TryBot-Result: Gobot Gobot --- src/net/http/h2_bundle.go | 34 ++++++++++++++++++++++++++++------ src/net/http/serve_test.go | 2 -- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 36ebeeaf34..57bc0a5fb5 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1,4 +1,4 @@ -// Code generated by golang.org/x/tools/cmd/bundle. +// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT. //go:generate bundle -o h2_bundle.go -prefix http2 -underscore golang.org/x/net/http2 // Package http2 implements the HTTP/2 protocol. @@ -2282,7 +2282,11 @@ func (cc *http2ClientConn) Ping(ctx context.Context) error { return cc.ping(ctx) } -func http2cloneTLSConfig(c *tls.Config) *tls.Config { return c.Clone() } +func http2cloneTLSConfig(c *tls.Config) *tls.Config { + c2 := c.Clone() + c2.GetClientCertificate = c.GetClientCertificate + return c2 +} var _ Pusher = (*http2responseWriter)(nil) @@ -3439,9 +3443,10 @@ type http2stream struct { numTrailerValues int64 weight uint8 state http2streamState - resetQueued bool // RST_STREAM queued for write; set by sc.resetStream - gotTrailerHeader bool // HEADER frame for trailers was seen - wroteHeaders bool // whether we wrote headers (not status 100) + resetQueued bool // RST_STREAM queued for write; set by sc.resetStream + gotTrailerHeader bool // HEADER frame for trailers was seen + wroteHeaders bool // whether we wrote headers (not status 100) + writeDeadline *time.Timer // nil if unused trailer Header // accumulated trailers reqTrailer Header // handler's Request.Trailer @@ -3698,6 +3703,10 @@ func (sc *http2serverConn) serve() { loopNum++ select { case wr := <-sc.wantWriteFrameCh: + if se, ok := wr.write.(http2StreamError); ok { + sc.resetStream(se) + break + } sc.writeFrame(wr) case spr := <-sc.wantStartPushCh: sc.startPush(spr) @@ -3939,7 +3948,8 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) { case http2stateOpen: st.state = http2stateHalfClosedLocal - sc.resetStream(http2streamError(st.id, http2ErrCodeCancel)) + + sc.resetStream(http2streamError(st.id, http2ErrCodeNo)) case http2stateHalfClosedRemote: sc.closeStream(st, http2errHandlerComplete) } @@ -4204,6 +4214,9 @@ func (sc *http2serverConn) closeStream(st *http2stream, err error) { panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state)) } st.state = http2stateClosed + if st.writeDeadline != nil { + st.writeDeadline.Stop() + } if st.isPushed() { sc.curPushedStreams-- } else { @@ -4403,6 +4416,12 @@ func (st *http2stream) copyTrailersToHandlerRequest() { } } +// onWriteTimeout is run on its own goroutine (from time.AfterFunc) +// when the stream's WriteTimeout has fired. +func (st *http2stream) onWriteTimeout() { + st.sc.writeFrameFromHandler(http2FrameWriteRequest{write: http2streamError(st.id, http2ErrCodeInternal)}) +} + func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { sc.serveG.check() id := f.StreamID @@ -4547,6 +4566,9 @@ func (sc *http2serverConn) newStream(id, pusherID uint32, state http2streamState st.flow.add(sc.initialStreamSendWindowSize) st.inflow.conn = &sc.inflow st.inflow.add(sc.srv.initialStreamRecvWindowSize()) + if sc.hs.WriteTimeout != 0 { + st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout) + } sc.streams[id] = st sc.writeSched.OpenStream(st.id, http2OpenStreamOptions{PusherID: pusherID}) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index c9ca2a697f..5ead2c00eb 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -661,7 +661,6 @@ func tryTimeouts(t *testing.T, testFunc func(timeout time.Duration) error) { // Test that the HTTP/2 server RSTs stream on slow write. func TestHTTP2WriteDeadlineEnforcedPerStream(t *testing.T) { - t.Skip("disabled until Issue 18437 is fixed") if testing.Short() { t.Skip("skipping in short mode") } @@ -723,7 +722,6 @@ func testHTTP2WriteDeadlineEnforcedPerStream(timeout time.Duration) error { // Test that the HTTP/2 server does not send RST when WriteDeadline not set. func TestHTTP2NoWriteDeadline(t *testing.T) { - t.Skip("disabled until Issue 18437 is fixed") if testing.Short() { t.Skip("skipping in short mode") }