...

Source file src/k8s.io/client-go/transport/spdy/spdy.go

Documentation: k8s.io/client-go/transport/spdy

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    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  // Upgrader validates a response from the server after a SPDY upgrade.
    31  type Upgrader interface {
    32  	// NewConnection validates the response and creates a new Connection.
    33  	NewConnection(resp *http.Response) (httpstream.Connection, error)
    34  }
    35  
    36  // RoundTripperFor returns a round tripper and upgrader to use with SPDY.
    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  // dialer implements the httpstream.Dialer interface.
    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  // NewDialer will create a dialer that connects to the provided URL and upgrades the connection to SPDY.
    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  // Negotiate opens a connection to a remote server and attempts to negotiate
    91  // a SPDY connection. Upon success, it returns the connection and the protocol selected by
    92  // the server. The client transport must use the upgradeRoundTripper - see RoundTripperFor.
    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