diff --git a/http2/server.go b/http2/server.go index c5d081081..d2f14b12c 100644 --- a/http2/server.go +++ b/http2/server.go @@ -1639,7 +1639,7 @@ func (sc *serverConn) closeStream(st *stream, err error) { delete(sc.streams, st.id) if len(sc.streams) == 0 { sc.setConnState(http.StateIdle) - if sc.srv.IdleTimeout > 0 { + if sc.srv.IdleTimeout > 0 && sc.idleTimer != nil { sc.idleTimer.Reset(sc.srv.IdleTimeout) } if h1ServerKeepAlivesDisabled(sc.hs) { diff --git a/http2/server_test.go b/http2/server_test.go index 61c773a54..f5aec44aa 100644 --- a/http2/server_test.go +++ b/http2/server_test.go @@ -4880,3 +4880,23 @@ func TestServerContinuationAfterInvalidHeader(t *testing.T) { t.Errorf("connection closed with no GOAWAY frame; want one") } } + +func TestServerUpgradeRequestPrefaceFailure(t *testing.T) { + // An h2c upgrade request fails when the client preface is not as expected. + s2 := &Server{ + // Setting IdleTimeout triggers #67168. + IdleTimeout: 60 * time.Minute, + } + c1, c2 := net.Pipe() + donec := make(chan struct{}) + go func() { + defer close(donec) + s2.ServeConn(c1, &ServeConnOpts{ + UpgradeRequest: httptest.NewRequest("GET", "/", nil), + }) + }() + // The server expects to see the HTTP/2 preface, + // but we close the connection instead. + c2.Close() + <-donec +}