forked from quic-go/quic-go
http3: make it possible to send HEAD requests in 0-RTT (#4378)
This commit is contained in:
@@ -21,9 +21,14 @@ import (
|
|||||||
"github.com/quic-go/qpack"
|
"github.com/quic-go/qpack"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MethodGet0RTT allows a GET request to be sent using 0-RTT.
|
const (
|
||||||
// Note that 0-RTT data doesn't provide replay protection.
|
// MethodGet0RTT allows a GET request to be sent using 0-RTT.
|
||||||
const MethodGet0RTT = "GET_0RTT"
|
// Note that 0-RTT doesn't provide replay protection and should only be used for idempotent requests.
|
||||||
|
MethodGet0RTT = "GET_0RTT"
|
||||||
|
// MethodHead0RTT allows a HEAD request to be sent using 0-RTT.
|
||||||
|
// Note that 0-RTT doesn't provide replay protection and should only be used for idempotent requests.
|
||||||
|
MethodHead0RTT = "HEAD_0RTT"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultUserAgent = "quic-go HTTP/3"
|
defaultUserAgent = "quic-go HTTP/3"
|
||||||
@@ -298,9 +303,12 @@ func (c *client) roundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Respon
|
|||||||
conn := *c.conn.Load()
|
conn := *c.conn.Load()
|
||||||
|
|
||||||
// Immediately send out this request, if this is a 0-RTT request.
|
// Immediately send out this request, if this is a 0-RTT request.
|
||||||
if req.Method == MethodGet0RTT {
|
switch req.Method {
|
||||||
|
case MethodGet0RTT:
|
||||||
req.Method = http.MethodGet
|
req.Method = http.MethodGet
|
||||||
} else {
|
case MethodHead0RTT:
|
||||||
|
req.Method = http.MethodHead
|
||||||
|
default:
|
||||||
// wait for the handshake to complete
|
// wait for the handshake to complete
|
||||||
select {
|
select {
|
||||||
case <-conn.HandshakeComplete():
|
case <-conn.HandshakeComplete():
|
||||||
|
|||||||
@@ -807,22 +807,27 @@ var _ = Describe("Client", func() {
|
|||||||
Expect(err).To(MatchError(testErr))
|
Expect(err).To(MatchError(testErr))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("performs a 0-RTT request", func() {
|
DescribeTable(
|
||||||
testErr := errors.New("stream open error")
|
"performs a 0-RTT request",
|
||||||
req.Method = MethodGet0RTT
|
func(method, serialized string) {
|
||||||
// don't EXPECT any calls to HandshakeComplete()
|
testErr := errors.New("stream open error")
|
||||||
conn.EXPECT().OpenStreamSync(context.Background()).Return(str, nil)
|
req.Method = method
|
||||||
buf := &bytes.Buffer{}
|
// don't EXPECT any calls to HandshakeComplete()
|
||||||
str.EXPECT().Write(gomock.Any()).DoAndReturn(buf.Write).AnyTimes()
|
conn.EXPECT().OpenStreamSync(context.Background()).Return(str, nil)
|
||||||
str.EXPECT().Close()
|
buf := &bytes.Buffer{}
|
||||||
str.EXPECT().CancelWrite(gomock.Any())
|
str.EXPECT().Write(gomock.Any()).DoAndReturn(buf.Write).AnyTimes()
|
||||||
str.EXPECT().Read(gomock.Any()).DoAndReturn(func([]byte) (int, error) {
|
str.EXPECT().Close()
|
||||||
return 0, testErr
|
str.EXPECT().CancelWrite(gomock.Any())
|
||||||
})
|
str.EXPECT().Read(gomock.Any()).DoAndReturn(func([]byte) (int, error) {
|
||||||
_, err := cl.RoundTripOpt(req, RoundTripOpt{})
|
return 0, testErr
|
||||||
Expect(err).To(MatchError(testErr))
|
})
|
||||||
Expect(decodeHeader(buf)).To(HaveKeyWithValue(":method", "GET"))
|
_, err := cl.RoundTripOpt(req, RoundTripOpt{})
|
||||||
})
|
Expect(err).To(MatchError(testErr))
|
||||||
|
Expect(decodeHeader(buf)).To(HaveKeyWithValue(":method", serialized))
|
||||||
|
},
|
||||||
|
Entry("GET", MethodGet0RTT, http.MethodGet),
|
||||||
|
Entry("HEAD", MethodHead0RTT, http.MethodHead),
|
||||||
|
)
|
||||||
|
|
||||||
It("returns a response", func() {
|
It("returns a response", func() {
|
||||||
rspBuf := bytes.NewBuffer(getResponse(418))
|
rspBuf := bytes.NewBuffer(getResponse(418))
|
||||||
|
|||||||
Reference in New Issue
Block a user