Skip to content

Commit

Permalink
http2: support Server.ReadTimeout
Browse files Browse the repository at this point in the history
Return an error when reading from the request body in a server
handler after Server.ReadTimeout expires.

Tested by net/http CL 446255.

For golang/go#49837

Change-Id: Idcc3d92209f944bd7fead832525fd563b50bcebc
Reviewed-on: https://go-review.googlesource.com/c/net/+/446256
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
  • Loading branch information
neild committed Nov 4, 2022
1 parent d7f77dc commit a870f35
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions http2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ type stream struct {
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)
readDeadline *time.Timer // nil if unused
writeDeadline *time.Timer // nil if unused

trailer http.Header // accumulated trailers
Expand Down Expand Up @@ -1579,6 +1580,9 @@ func (sc *serverConn) closeStream(st *stream, err error) {
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
}
st.state = stateClosed
if st.readDeadline != nil {
st.readDeadline.Stop()
}
if st.writeDeadline != nil {
st.writeDeadline.Stop()
}
Expand Down Expand Up @@ -1842,6 +1846,14 @@ func (st *stream) copyTrailersToHandlerRequest() {
}
}

// onReadTimeout is run on its own goroutine (from time.AfterFunc)
// when the stream's ReadTimeout has fired.
func (st *stream) onReadTimeout() {
// Wrap the ErrDeadlineExceeded to avoid callers depending on us
// returning the bare error.
st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
}

// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
// when the stream's WriteTimeout has fired.
func (st *stream) onWriteTimeout() {
Expand Down Expand Up @@ -1953,6 +1965,9 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// (in Go 1.8), though. That's a more sane option anyway.
if sc.hs.ReadTimeout != 0 {
sc.conn.SetReadDeadline(time.Time{})
if st.body != nil {
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
}
}

go sc.runHandler(rw, req, handler)
Expand Down

0 comments on commit a870f35

Please sign in to comment.