define a new Method for 0-RTT GET requests on the http.Request

This commit is contained in:
Marten Seemann
2020-01-26 11:28:07 +07:00
parent af1e8f4c78
commit 91543322f6
2 changed files with 33 additions and 5 deletions

View File

@@ -15,6 +15,10 @@ import (
"github.com/marten-seemann/qpack"
)
// MethodGet0RTT allows a GET request to be sent using 0-RTT.
// Note that 0-RTT data doesn't provide replay protection.
const MethodGet0RTT = "GET_0RTT"
const defaultUserAgent = "quic-go HTTP/3"
const defaultMaxResponseHeaderBytes = 10 * 1 << 20 // 10 MB
@@ -150,11 +154,16 @@ func (c *client) RoundTrip(req *http.Request) (*http.Response, error) {
return nil, c.handshakeErr
}
// wait for the handshake to complete
select {
case <-c.session.HandshakeComplete().Done():
case <-req.Context().Done():
return nil, req.Context().Err()
// Immediately send out this request, if this is a 0-RTT request.
if req.Method == MethodGet0RTT {
req.Method = http.MethodGet
} else {
// wait for the handshake to complete
select {
case <-c.session.HandshakeComplete().Done():
case <-req.Context().Done():
return nil, req.Context().Err()
}
}
str, err := c.session.OpenStreamSync(req.Context())

View File

@@ -187,6 +187,25 @@ var _ = Describe("Client", func() {
Expect(err).ToNot(HaveOccurred())
})
It("performs a 0-RTT request", func() {
testErr := errors.New("stream open error")
request.Method = MethodGet0RTT
// don't EXPECT any calls to HandshakeComplete()
sess.EXPECT().OpenStreamSync(context.Background()).Return(str, nil)
buf := &bytes.Buffer{}
str.EXPECT().Write(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
return buf.Write(p)
}).AnyTimes()
str.EXPECT().Close()
str.EXPECT().CancelWrite(gomock.Any())
str.EXPECT().Read(gomock.Any()).DoAndReturn(func([]byte) (int, error) {
return 0, testErr
})
_, err := client.RoundTrip(request)
Expect(err).To(MatchError(testErr))
Expect(decodeHeader(buf)).To(HaveKeyWithValue(":method", "GET"))
})
It("returns a response", func() {
rspBuf := &bytes.Buffer{}
rw := newResponseWriter(rspBuf, utils.DefaultLogger)