don't close the request stream when http3.DataStreamer was used (#3413)

This commit is contained in:
Marten Seemann 2022-05-20 11:53:44 +02:00 committed by GitHub
parent 0ec8ee3cff
commit 6511723c28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 11 deletions

View file

@ -582,15 +582,17 @@ func (s *Server) handleRequest(conn quic.Connection, str quic.Stream, decoder *q
handler.ServeHTTP(r, req)
}()
if !r.usedDataStream() {
if panicked {
r.WriteHeader(500)
} else {
r.WriteHeader(200)
}
// If the EOF was read by the handler, CancelRead() is a no-op.
str.CancelRead(quic.StreamErrorCode(errorNoError))
if r.usedDataStream() {
return requestError{err: errHijacked}
}
if panicked {
r.WriteHeader(500)
} else {
r.WriteHeader(200)
}
// If the EOF was read by the handler, CancelRead() is a no-op.
str.CancelRead(quic.StreamErrorCode(errorNoError))
return requestError{}
}

View file

@ -228,13 +228,37 @@ var _ = Describe("Server", func() {
str.Write([]byte("foobar"))
})
rspWritten := make(chan struct{})
setRequest(encodeRequest(exampleGetRequest))
str.EXPECT().Context().Return(reqContext)
str.EXPECT().Write([]byte("foobar"))
str.EXPECT().Write([]byte("foobar")).Do(func(b []byte) (int, error) {
close(rspWritten)
return len(b), nil
})
// don't EXPECT CancelRead()
serr := s.handleRequest(conn, str, qpackDecoder, nil)
Expect(serr.err).ToNot(HaveOccurred())
ctrlStr := mockquic.NewMockStream(mockCtrl)
ctrlStr.EXPECT().Write(gomock.Any()).AnyTimes()
conn.EXPECT().OpenUniStream().Return(ctrlStr, nil)
conn.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
<-rspWritten
return nil, errors.New("done")
})
conn.EXPECT().AcceptStream(gomock.Any()).Return(str, nil)
conn.EXPECT().AcceptStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.Stream, error) {
<-rspWritten
return nil, errors.New("done")
})
done := make(chan struct{})
go func() {
defer GinkgoRecover()
defer close(done)
s.handleConn(conn)
}()
Eventually(rspWritten).Should(BeClosed())
time.Sleep(50 * time.Millisecond) // make sure that after str.Write there are no further calls to stream methods
Eventually(done).Should(BeClosed())
})
Context("hijacking unidirectional streams", func() {