implement a basic QUIC RoundTripper

This commit is contained in:
Marten Seemann
2016-12-19 00:32:10 +07:00
parent c547ced3ce
commit 40a6577dc3
3 changed files with 87 additions and 0 deletions

View File

@@ -41,6 +41,8 @@ type Client struct {
responses map[protocol.StreamID]chan *http.Response responses map[protocol.StreamID]chan *http.Response
} }
var _ h2quicClient = &Client{}
// NewClient creates a new client // NewClient creates a new client
func NewClient(hostname string) (*Client, error) { func NewClient(hostname string) (*Client, error) {
c := &Client{ c := &Client{

49
h2quic/roundtrip.go Normal file
View File

@@ -0,0 +1,49 @@
package h2quic
import (
"net/http"
"sync"
)
type h2quicClient interface {
Do(*http.Request) (*http.Response, error)
}
// QuicRoundTripper implements the http.RoundTripper interface
type QuicRoundTripper struct {
mutex sync.Mutex
clients map[string]h2quicClient
}
var _ http.RoundTripper = &QuicRoundTripper{}
// RoundTrip does a round trip
func (r *QuicRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
hostname := authorityAddr("https", hostnameFromRequest(req))
client, err := r.getClient(hostname)
if err != nil {
return nil, err
}
return client.Do(req)
}
func (r *QuicRoundTripper) getClient(hostname string) (h2quicClient, error) {
r.mutex.Lock()
defer r.mutex.Unlock()
if r.clients == nil {
r.clients = make(map[string]h2quicClient)
}
client, ok := r.clients[hostname]
if !ok {
var err error
client, err = NewClient(hostname)
if err != nil {
return nil, err
}
r.clients[hostname] = client
}
return client, nil
}

36
h2quic/roundtrip_test.go Normal file
View File

@@ -0,0 +1,36 @@
package h2quic
import (
"net/http"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type mockQuicRoundTripper struct{}
func (m *mockQuicRoundTripper) Do(req *http.Request) (*http.Response, error) {
return &http.Response{Request: req}, nil
}
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, _ := rt.RoundTrip(req1)
Expect(rsp.Request).To(Equal(req1))
Expect(rt.clients).To(HaveLen(1))
})
})