1
16
17 package spdy
18
19 import (
20 "fmt"
21 "net/http"
22 "net/url"
23 "time"
24
25 "k8s.io/apimachinery/pkg/util/httpstream"
26 "k8s.io/apimachinery/pkg/util/httpstream/spdy"
27 restclient "k8s.io/client-go/rest"
28 )
29
30
31 type Upgrader interface {
32
33 NewConnection(resp *http.Response) (httpstream.Connection, error)
34 }
35
36
37 func RoundTripperFor(config *restclient.Config) (http.RoundTripper, Upgrader, error) {
38 tlsConfig, err := restclient.TLSConfigFor(config)
39 if err != nil {
40 return nil, nil, err
41 }
42 proxy := http.ProxyFromEnvironment
43 if config.Proxy != nil {
44 proxy = config.Proxy
45 }
46 upgradeRoundTripper, err := spdy.NewRoundTripperWithConfig(spdy.RoundTripperConfig{
47 TLS: tlsConfig,
48 Proxier: proxy,
49 PingPeriod: time.Second * 5,
50 UpgradeTransport: nil,
51 })
52 if err != nil {
53 return nil, nil, err
54 }
55 wrapper, err := restclient.HTTPWrappersForConfig(config, upgradeRoundTripper)
56 if err != nil {
57 return nil, nil, err
58 }
59 return wrapper, upgradeRoundTripper, nil
60 }
61
62
63 type dialer struct {
64 client *http.Client
65 upgrader Upgrader
66 method string
67 url *url.URL
68 }
69
70 var _ httpstream.Dialer = &dialer{}
71
72
73 func NewDialer(upgrader Upgrader, client *http.Client, method string, url *url.URL) httpstream.Dialer {
74 return &dialer{
75 client: client,
76 upgrader: upgrader,
77 method: method,
78 url: url,
79 }
80 }
81
82 func (d *dialer) Dial(protocols ...string) (httpstream.Connection, string, error) {
83 req, err := http.NewRequest(d.method, d.url.String(), nil)
84 if err != nil {
85 return nil, "", fmt.Errorf("error creating request: %v", err)
86 }
87 return Negotiate(d.upgrader, d.client, req, protocols...)
88 }
89
90
91
92
93 func Negotiate(upgrader Upgrader, client *http.Client, req *http.Request, protocols ...string) (httpstream.Connection, string, error) {
94 for i := range protocols {
95 req.Header.Add(httpstream.HeaderProtocolVersion, protocols[i])
96 }
97 resp, err := client.Do(req)
98 if err != nil {
99 return nil, "", fmt.Errorf("error sending request: %v", err)
100 }
101 defer resp.Body.Close()
102 conn, err := upgrader.NewConnection(resp)
103 if err != nil {
104 return nil, "", err
105 }
106 return conn, resp.Header.Get(httpstream.HeaderProtocolVersion), nil
107 }
108
View as plain text