forked from quic-go/quic-go
close the quic client on protocol errors in h2quic client
This commit is contained in:
@@ -162,12 +162,15 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
c.responses[dataStreamID] = hdrChan
|
||||
c.mutex.Unlock()
|
||||
|
||||
// TODO: think about what to do with a TooManyOpenStreams error. Wait and retry?
|
||||
dataStream, err := c.client.OpenStream(dataStreamID)
|
||||
if err != nil {
|
||||
c.Close(err)
|
||||
return nil, err
|
||||
}
|
||||
err = c.requestWriter.WriteRequest(req, dataStreamID)
|
||||
if err != nil {
|
||||
c.Close(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -181,6 +184,7 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
|
||||
// if an error occured on the header stream
|
||||
if res == nil {
|
||||
c.Close(c.headerErr)
|
||||
return nil, c.headerErr
|
||||
}
|
||||
|
||||
@@ -203,6 +207,11 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Close closes the client
|
||||
func (c *Client) Close(e error) {
|
||||
_ = c.client.Close(e)
|
||||
}
|
||||
|
||||
// copied from net/transport.go
|
||||
|
||||
// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
|
||||
|
||||
@@ -14,11 +14,12 @@ import (
|
||||
)
|
||||
|
||||
type mockQuicClient struct {
|
||||
streams map[protocol.StreamID]*mockStream
|
||||
streams map[protocol.StreamID]*mockStream
|
||||
closeErr error
|
||||
}
|
||||
|
||||
func (m *mockQuicClient) Close(error) error { panic("not implemented") }
|
||||
func (m *mockQuicClient) Listen() error { panic("not implemented") }
|
||||
func (m *mockQuicClient) Close(e error) error { m.closeErr = e; return nil }
|
||||
func (m *mockQuicClient) Listen() error { panic("not implemented") }
|
||||
func (m *mockQuicClient) OpenStream(id protocol.StreamID) (utils.Stream, error) {
|
||||
_, ok := m.streams[id]
|
||||
if ok {
|
||||
@@ -121,6 +122,28 @@ var _ = Describe("Client", func() {
|
||||
close(done)
|
||||
})
|
||||
|
||||
It("closes the quic client when encountering an error on the header stream", func() {
|
||||
req, err := http.NewRequest("https", "https://quic.clemente.io:1337/file1.dat", nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
headerStream.dataToRead.Write([]byte("invalid response"))
|
||||
go client.handleHeaderStream()
|
||||
|
||||
var doRsp *http.Response
|
||||
var doErr error
|
||||
var doReturned bool
|
||||
go func() {
|
||||
doRsp, doErr = client.Do(req)
|
||||
doReturned = true
|
||||
}()
|
||||
|
||||
Eventually(func() bool { return doReturned }).Should(BeTrue())
|
||||
Expect(client.headerErr).To(HaveOccurred())
|
||||
Expect(doErr).To(MatchError(client.headerErr))
|
||||
Expect(doRsp).To(BeNil())
|
||||
Expect(client.client.(*mockQuicClient).closeErr).To(MatchError(client.headerErr))
|
||||
})
|
||||
|
||||
Context("validating the address", func() {
|
||||
It("refuses to do requests for the wrong host", func() {
|
||||
req, err := http.NewRequest("https", "https://quic.clemente.io:1336/foobar.html", nil)
|
||||
|
||||
Reference in New Issue
Block a user