github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/http.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     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 util
    18  
    19  import (
    20  	"crypto/tls"
    21  	"fmt"
    22  	"io"
    23  	"net"
    24  	"net/http"
    25  	"net/url"
    26  	"strings"
    27  )
    28  
    29  // IsProbableEOF returns true if the given error resembles a connection termination
    30  // scenario that would justify assuming that the watch is empty.
    31  // These errors are what the Go http stack returns back to us which are general
    32  // connection closure errors (strongly correlated) and callers that need to
    33  // differentiate probable errors in connection behavior between normal "this is
    34  // disconnected" should use the method.
    35  func IsProbableEOF(err error) bool {
    36  	if uerr, ok := err.(*url.Error); ok {
    37  		err = uerr.Err
    38  	}
    39  	switch {
    40  	case err == io.EOF:
    41  		return true
    42  	case err.Error() == "http: can't write HTTP request on broken connection":
    43  		return true
    44  	case strings.Contains(err.Error(), "connection reset by peer"):
    45  		return true
    46  	case strings.Contains(strings.ToLower(err.Error()), "use of closed network connection"):
    47  		return true
    48  	}
    49  	return false
    50  }
    51  
    52  var defaultTransport = http.DefaultTransport.(*http.Transport)
    53  
    54  // SetTransportDefaults applies the defaults from http.DefaultTransport
    55  // for the Proxy, Dial, and TLSHandshakeTimeout fields if unset
    56  func SetTransportDefaults(t *http.Transport) *http.Transport {
    57  	if t.Proxy == nil {
    58  		t.Proxy = defaultTransport.Proxy
    59  	}
    60  	if t.Dial == nil {
    61  		t.Dial = defaultTransport.Dial
    62  	}
    63  	if t.TLSHandshakeTimeout == 0 {
    64  		t.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout
    65  	}
    66  	return t
    67  }
    68  
    69  type RoundTripperWrapper interface {
    70  	http.RoundTripper
    71  	WrappedRoundTripper() http.RoundTripper
    72  }
    73  
    74  type DialFunc func(net, addr string) (net.Conn, error)
    75  
    76  func Dialer(transport http.RoundTripper) (DialFunc, error) {
    77  	if transport == nil {
    78  		return nil, nil
    79  	}
    80  
    81  	switch transport := transport.(type) {
    82  	case *http.Transport:
    83  		return transport.Dial, nil
    84  	case RoundTripperWrapper:
    85  		return Dialer(transport.WrappedRoundTripper())
    86  	default:
    87  		return nil, fmt.Errorf("unknown transport type: %v", transport)
    88  	}
    89  }
    90  
    91  func TLSClientConfig(transport http.RoundTripper) (*tls.Config, error) {
    92  	if transport == nil {
    93  		return nil, nil
    94  	}
    95  
    96  	switch transport := transport.(type) {
    97  	case *http.Transport:
    98  		return transport.TLSClientConfig, nil
    99  	case RoundTripperWrapper:
   100  		return TLSClientConfig(transport.WrappedRoundTripper())
   101  	default:
   102  		return nil, fmt.Errorf("unknown transport type: %v", transport)
   103  	}
   104  }