137 lines
3.5 KiB
Go
137 lines
3.5 KiB
Go
|
package h2quic
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"io"
|
||
|
"net/http"
|
||
|
|
||
|
. "github.com/onsi/ginkgo"
|
||
|
. "github.com/onsi/gomega"
|
||
|
)
|
||
|
|
||
|
type mockQuicRoundTripper struct{}
|
||
|
|
||
|
func (m *mockQuicRoundTripper) Dial() error {
|
||
|
return nil
|
||
|
}
|
||
|
func (m *mockQuicRoundTripper) Do(req *http.Request) (*http.Response, error) {
|
||
|
return &http.Response{Request: req}, nil
|
||
|
}
|
||
|
|
||
|
type mockBody struct {
|
||
|
reader bytes.Reader
|
||
|
readErr error
|
||
|
closeErr error
|
||
|
closed bool
|
||
|
}
|
||
|
|
||
|
func (m *mockBody) Read(p []byte) (int, error) {
|
||
|
if m.readErr != nil {
|
||
|
return 0, m.readErr
|
||
|
}
|
||
|
return m.reader.Read(p)
|
||
|
}
|
||
|
|
||
|
func (m *mockBody) SetData(data []byte) {
|
||
|
m.reader = *bytes.NewReader(data)
|
||
|
}
|
||
|
|
||
|
func (m *mockBody) Close() error {
|
||
|
m.closed = true
|
||
|
return m.closeErr
|
||
|
}
|
||
|
|
||
|
// make sure the mockBody can be used as a http.Request.Body
|
||
|
var _ io.ReadCloser = &mockBody{}
|
||
|
|
||
|
var _ = Describe("RoundTripper", func() {
|
||
|
var (
|
||
|
rt *QuicRoundTripper
|
||
|
req1 *http.Request
|
||
|
)
|
||
|
|
||
|
BeforeEach(func() {
|
||
|
rt = &QuicRoundTripper{}
|
||
|
var err error
|
||
|
req1, err = http.NewRequest("GET", "https://www.example.org/file1.html", nil)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("reuses existing clients", func() {
|
||
|
rt.clients = make(map[string]h2quicClient)
|
||
|
rt.clients["www.example.org:443"] = &mockQuicRoundTripper{}
|
||
|
rsp, err := rt.RoundTrip(req1)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(rsp.Request).To(Equal(req1))
|
||
|
Expect(rt.clients).To(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("disable compression", func() {
|
||
|
Expect(rt.disableCompression()).To(BeFalse())
|
||
|
rt.DisableCompression = true
|
||
|
Expect(rt.disableCompression()).To(BeTrue())
|
||
|
})
|
||
|
|
||
|
Context("validating request", func() {
|
||
|
It("rejects plain HTTP requests", func() {
|
||
|
req, err := http.NewRequest("GET", "http://www.example.org/", nil)
|
||
|
req.Body = &mockBody{}
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
_, err = rt.RoundTrip(req)
|
||
|
Expect(err).To(MatchError("quic: unsupported protocol scheme: http"))
|
||
|
Expect(req.Body.(*mockBody).closed).To(BeTrue())
|
||
|
})
|
||
|
|
||
|
It("rejects requests without a URL", func() {
|
||
|
req1.URL = nil
|
||
|
req1.Body = &mockBody{}
|
||
|
_, err := rt.RoundTrip(req1)
|
||
|
Expect(err).To(MatchError("quic: nil Request.URL"))
|
||
|
Expect(req1.Body.(*mockBody).closed).To(BeTrue())
|
||
|
})
|
||
|
|
||
|
It("rejects request without a URL Host", func() {
|
||
|
req1.URL.Host = ""
|
||
|
req1.Body = &mockBody{}
|
||
|
_, err := rt.RoundTrip(req1)
|
||
|
Expect(err).To(MatchError("quic: no Host in request URL"))
|
||
|
Expect(req1.Body.(*mockBody).closed).To(BeTrue())
|
||
|
})
|
||
|
|
||
|
It("doesn't try to close the body if the request doesn't have one", func() {
|
||
|
req1.URL = nil
|
||
|
Expect(req1.Body).To(BeNil())
|
||
|
_, err := rt.RoundTrip(req1)
|
||
|
Expect(err).To(MatchError("quic: nil Request.URL"))
|
||
|
})
|
||
|
|
||
|
It("rejects requests without a header", func() {
|
||
|
req1.Header = nil
|
||
|
req1.Body = &mockBody{}
|
||
|
_, err := rt.RoundTrip(req1)
|
||
|
Expect(err).To(MatchError("quic: nil Request.Header"))
|
||
|
Expect(req1.Body.(*mockBody).closed).To(BeTrue())
|
||
|
})
|
||
|
|
||
|
It("rejects requests with invalid header name fields", func() {
|
||
|
req1.Header.Add("foobär", "value")
|
||
|
_, err := rt.RoundTrip(req1)
|
||
|
Expect(err).To(MatchError("quic: invalid http header field name \"foobär\""))
|
||
|
})
|
||
|
|
||
|
It("rejects requests with invalid header name values", func() {
|
||
|
req1.Header.Add("foo", string([]byte{0x7}))
|
||
|
_, err := rt.RoundTrip(req1)
|
||
|
Expect(err.Error()).To(ContainSubstring("quic: invalid http header field value"))
|
||
|
})
|
||
|
|
||
|
It("rejects requests with an invalid request method", func() {
|
||
|
req1.Method = "foobär"
|
||
|
req1.Body = &mockBody{}
|
||
|
_, err := rt.RoundTrip(req1)
|
||
|
Expect(err).To(MatchError("quic: invalid method \"foobär\""))
|
||
|
Expect(req1.Body.(*mockBody).closed).To(BeTrue())
|
||
|
})
|
||
|
})
|
||
|
})
|