aboutsummaryrefslogtreecommitdiff
path: root/vendor/k8s.io/client-go/transport/round_trippers.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/client-go/transport/round_trippers.go')
-rw-r--r--vendor/k8s.io/client-go/transport/round_trippers.go564
1 files changed, 0 insertions, 564 deletions
diff --git a/vendor/k8s.io/client-go/transport/round_trippers.go b/vendor/k8s.io/client-go/transport/round_trippers.go
deleted file mode 100644
index 117a9c8c4..000000000
--- a/vendor/k8s.io/client-go/transport/round_trippers.go
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
-Copyright 2015 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package transport
-
-import (
- "fmt"
- "net/http"
- "strings"
- "time"
-
- "golang.org/x/oauth2"
- "k8s.io/klog"
-
- utilnet "k8s.io/apimachinery/pkg/util/net"
-)
-
-// HTTPWrappersForConfig wraps a round tripper with any relevant layered
-// behavior from the config. Exposed to allow more clients that need HTTP-like
-// behavior but then must hijack the underlying connection (like WebSocket or
-// HTTP2 clients). Pure HTTP clients should use the RoundTripper returned from
-// New.
-func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTripper, error) {
- if config.WrapTransport != nil {
- rt = config.WrapTransport(rt)
- }
-
- rt = DebugWrappers(rt)
-
- // Set authentication wrappers
- switch {
- case config.HasBasicAuth() && config.HasTokenAuth():
- return nil, fmt.Errorf("username/password or bearer token may be set, but not both")
- case config.HasTokenAuth():
- var err error
- rt, err = NewBearerAuthWithRefreshRoundTripper(config.BearerToken, config.BearerTokenFile, rt)
- if err != nil {
- return nil, err
- }
- case config.HasBasicAuth():
- rt = NewBasicAuthRoundTripper(config.Username, config.Password, rt)
- }
- if len(config.UserAgent) > 0 {
- rt = NewUserAgentRoundTripper(config.UserAgent, rt)
- }
- if len(config.Impersonate.UserName) > 0 ||
- len(config.Impersonate.Groups) > 0 ||
- len(config.Impersonate.Extra) > 0 {
- rt = NewImpersonatingRoundTripper(config.Impersonate, rt)
- }
- return rt, nil
-}
-
-// DebugWrappers wraps a round tripper and logs based on the current log level.
-func DebugWrappers(rt http.RoundTripper) http.RoundTripper {
- switch {
- case bool(klog.V(9)):
- rt = newDebuggingRoundTripper(rt, debugCurlCommand, debugURLTiming, debugResponseHeaders)
- case bool(klog.V(8)):
- rt = newDebuggingRoundTripper(rt, debugJustURL, debugRequestHeaders, debugResponseStatus, debugResponseHeaders)
- case bool(klog.V(7)):
- rt = newDebuggingRoundTripper(rt, debugJustURL, debugRequestHeaders, debugResponseStatus)
- case bool(klog.V(6)):
- rt = newDebuggingRoundTripper(rt, debugURLTiming)
- }
-
- return rt
-}
-
-type requestCanceler interface {
- CancelRequest(*http.Request)
-}
-
-type authProxyRoundTripper struct {
- username string
- groups []string
- extra map[string][]string
-
- rt http.RoundTripper
-}
-
-// NewAuthProxyRoundTripper provides a roundtripper which will add auth proxy fields to requests for
-// authentication terminating proxy cases
-// assuming you pull the user from the context:
-// username is the user.Info.GetName() of the user
-// groups is the user.Info.GetGroups() of the user
-// extra is the user.Info.GetExtra() of the user
-// extra can contain any additional information that the authenticator
-// thought was interesting, for example authorization scopes.
-// In order to faithfully round-trip through an impersonation flow, these keys
-// MUST be lowercase.
-func NewAuthProxyRoundTripper(username string, groups []string, extra map[string][]string, rt http.RoundTripper) http.RoundTripper {
- return &authProxyRoundTripper{
- username: username,
- groups: groups,
- extra: extra,
- rt: rt,
- }
-}
-
-func (rt *authProxyRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- req = utilnet.CloneRequest(req)
- SetAuthProxyHeaders(req, rt.username, rt.groups, rt.extra)
-
- return rt.rt.RoundTrip(req)
-}
-
-// SetAuthProxyHeaders stomps the auth proxy header fields. It mutates its argument.
-func SetAuthProxyHeaders(req *http.Request, username string, groups []string, extra map[string][]string) {
- req.Header.Del("X-Remote-User")
- req.Header.Del("X-Remote-Group")
- for key := range req.Header {
- if strings.HasPrefix(strings.ToLower(key), strings.ToLower("X-Remote-Extra-")) {
- req.Header.Del(key)
- }
- }
-
- req.Header.Set("X-Remote-User", username)
- for _, group := range groups {
- req.Header.Add("X-Remote-Group", group)
- }
- for key, values := range extra {
- for _, value := range values {
- req.Header.Add("X-Remote-Extra-"+headerKeyEscape(key), value)
- }
- }
-}
-
-func (rt *authProxyRoundTripper) CancelRequest(req *http.Request) {
- if canceler, ok := rt.rt.(requestCanceler); ok {
- canceler.CancelRequest(req)
- } else {
- klog.Errorf("CancelRequest not implemented by %T", rt.rt)
- }
-}
-
-func (rt *authProxyRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt }
-
-type userAgentRoundTripper struct {
- agent string
- rt http.RoundTripper
-}
-
-func NewUserAgentRoundTripper(agent string, rt http.RoundTripper) http.RoundTripper {
- return &userAgentRoundTripper{agent, rt}
-}
-
-func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- if len(req.Header.Get("User-Agent")) != 0 {
- return rt.rt.RoundTrip(req)
- }
- req = utilnet.CloneRequest(req)
- req.Header.Set("User-Agent", rt.agent)
- return rt.rt.RoundTrip(req)
-}
-
-func (rt *userAgentRoundTripper) CancelRequest(req *http.Request) {
- if canceler, ok := rt.rt.(requestCanceler); ok {
- canceler.CancelRequest(req)
- } else {
- klog.Errorf("CancelRequest not implemented by %T", rt.rt)
- }
-}
-
-func (rt *userAgentRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt }
-
-type basicAuthRoundTripper struct {
- username string
- password string
- rt http.RoundTripper
-}
-
-// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a
-// request unless it has already been set.
-func NewBasicAuthRoundTripper(username, password string, rt http.RoundTripper) http.RoundTripper {
- return &basicAuthRoundTripper{username, password, rt}
-}
-
-func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- if len(req.Header.Get("Authorization")) != 0 {
- return rt.rt.RoundTrip(req)
- }
- req = utilnet.CloneRequest(req)
- req.SetBasicAuth(rt.username, rt.password)
- return rt.rt.RoundTrip(req)
-}
-
-func (rt *basicAuthRoundTripper) CancelRequest(req *http.Request) {
- if canceler, ok := rt.rt.(requestCanceler); ok {
- canceler.CancelRequest(req)
- } else {
- klog.Errorf("CancelRequest not implemented by %T", rt.rt)
- }
-}
-
-func (rt *basicAuthRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt }
-
-// These correspond to the headers used in pkg/apis/authentication. We don't want the package dependency,
-// but you must not change the values.
-const (
- // ImpersonateUserHeader is used to impersonate a particular user during an API server request
- ImpersonateUserHeader = "Impersonate-User"
-
- // ImpersonateGroupHeader is used to impersonate a particular group during an API server request.
- // It can be repeated multiplied times for multiple groups.
- ImpersonateGroupHeader = "Impersonate-Group"
-
- // ImpersonateUserExtraHeaderPrefix is a prefix for a header used to impersonate an entry in the
- // extra map[string][]string for user.Info. The key for the `extra` map is suffix.
- // The same key can be repeated multiple times to have multiple elements in the slice under a single key.
- // For instance:
- // Impersonate-Extra-Foo: one
- // Impersonate-Extra-Foo: two
- // results in extra["Foo"] = []string{"one", "two"}
- ImpersonateUserExtraHeaderPrefix = "Impersonate-Extra-"
-)
-
-type impersonatingRoundTripper struct {
- impersonate ImpersonationConfig
- delegate http.RoundTripper
-}
-
-// NewImpersonatingRoundTripper will add an Act-As header to a request unless it has already been set.
-func NewImpersonatingRoundTripper(impersonate ImpersonationConfig, delegate http.RoundTripper) http.RoundTripper {
- return &impersonatingRoundTripper{impersonate, delegate}
-}
-
-func (rt *impersonatingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- // use the user header as marker for the rest.
- if len(req.Header.Get(ImpersonateUserHeader)) != 0 {
- return rt.delegate.RoundTrip(req)
- }
- req = utilnet.CloneRequest(req)
- req.Header.Set(ImpersonateUserHeader, rt.impersonate.UserName)
-
- for _, group := range rt.impersonate.Groups {
- req.Header.Add(ImpersonateGroupHeader, group)
- }
- for k, vv := range rt.impersonate.Extra {
- for _, v := range vv {
- req.Header.Add(ImpersonateUserExtraHeaderPrefix+headerKeyEscape(k), v)
- }
- }
-
- return rt.delegate.RoundTrip(req)
-}
-
-func (rt *impersonatingRoundTripper) CancelRequest(req *http.Request) {
- if canceler, ok := rt.delegate.(requestCanceler); ok {
- canceler.CancelRequest(req)
- } else {
- klog.Errorf("CancelRequest not implemented by %T", rt.delegate)
- }
-}
-
-func (rt *impersonatingRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.delegate }
-
-type bearerAuthRoundTripper struct {
- bearer string
- source oauth2.TokenSource
- rt http.RoundTripper
-}
-
-// NewBearerAuthRoundTripper adds the provided bearer token to a request
-// unless the authorization header has already been set.
-func NewBearerAuthRoundTripper(bearer string, rt http.RoundTripper) http.RoundTripper {
- return &bearerAuthRoundTripper{bearer, nil, rt}
-}
-
-// NewBearerAuthRoundTripper adds the provided bearer token to a request
-// unless the authorization header has already been set.
-// If tokenFile is non-empty, it is periodically read,
-// and the last successfully read content is used as the bearer token.
-// If tokenFile is non-empty and bearer is empty, the tokenFile is read
-// immediately to populate the initial bearer token.
-func NewBearerAuthWithRefreshRoundTripper(bearer string, tokenFile string, rt http.RoundTripper) (http.RoundTripper, error) {
- if len(tokenFile) == 0 {
- return &bearerAuthRoundTripper{bearer, nil, rt}, nil
- }
- source := NewCachedFileTokenSource(tokenFile)
- if len(bearer) == 0 {
- token, err := source.Token()
- if err != nil {
- return nil, err
- }
- bearer = token.AccessToken
- }
- return &bearerAuthRoundTripper{bearer, source, rt}, nil
-}
-
-func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- if len(req.Header.Get("Authorization")) != 0 {
- return rt.rt.RoundTrip(req)
- }
-
- req = utilnet.CloneRequest(req)
- token := rt.bearer
- if rt.source != nil {
- if refreshedToken, err := rt.source.Token(); err == nil {
- token = refreshedToken.AccessToken
- }
- }
- req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
- return rt.rt.RoundTrip(req)
-}
-
-func (rt *bearerAuthRoundTripper) CancelRequest(req *http.Request) {
- if canceler, ok := rt.rt.(requestCanceler); ok {
- canceler.CancelRequest(req)
- } else {
- klog.Errorf("CancelRequest not implemented by %T", rt.rt)
- }
-}
-
-func (rt *bearerAuthRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt }
-
-// requestInfo keeps track of information about a request/response combination
-type requestInfo struct {
- RequestHeaders http.Header
- RequestVerb string
- RequestURL string
-
- ResponseStatus string
- ResponseHeaders http.Header
- ResponseErr error
-
- Duration time.Duration
-}
-
-// newRequestInfo creates a new RequestInfo based on an http request
-func newRequestInfo(req *http.Request) *requestInfo {
- return &requestInfo{
- RequestURL: req.URL.String(),
- RequestVerb: req.Method,
- RequestHeaders: req.Header,
- }
-}
-
-// complete adds information about the response to the requestInfo
-func (r *requestInfo) complete(response *http.Response, err error) {
- if err != nil {
- r.ResponseErr = err
- return
- }
- r.ResponseStatus = response.Status
- r.ResponseHeaders = response.Header
-}
-
-// toCurl returns a string that can be run as a command in a terminal (minus the body)
-func (r *requestInfo) toCurl() string {
- headers := ""
- for key, values := range r.RequestHeaders {
- for _, value := range values {
- headers += fmt.Sprintf(` -H %q`, fmt.Sprintf("%s: %s", key, value))
- }
- }
-
- return fmt.Sprintf("curl -k -v -X%s %s '%s'", r.RequestVerb, headers, r.RequestURL)
-}
-
-// debuggingRoundTripper will display information about the requests passing
-// through it based on what is configured
-type debuggingRoundTripper struct {
- delegatedRoundTripper http.RoundTripper
-
- levels map[debugLevel]bool
-}
-
-type debugLevel int
-
-const (
- debugJustURL debugLevel = iota
- debugURLTiming
- debugCurlCommand
- debugRequestHeaders
- debugResponseStatus
- debugResponseHeaders
-)
-
-func newDebuggingRoundTripper(rt http.RoundTripper, levels ...debugLevel) *debuggingRoundTripper {
- drt := &debuggingRoundTripper{
- delegatedRoundTripper: rt,
- levels: make(map[debugLevel]bool, len(levels)),
- }
- for _, v := range levels {
- drt.levels[v] = true
- }
- return drt
-}
-
-func (rt *debuggingRoundTripper) CancelRequest(req *http.Request) {
- if canceler, ok := rt.delegatedRoundTripper.(requestCanceler); ok {
- canceler.CancelRequest(req)
- } else {
- klog.Errorf("CancelRequest not implemented by %T", rt.delegatedRoundTripper)
- }
-}
-
-func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- reqInfo := newRequestInfo(req)
-
- if rt.levels[debugJustURL] {
- klog.Infof("%s %s", reqInfo.RequestVerb, reqInfo.RequestURL)
- }
- if rt.levels[debugCurlCommand] {
- klog.Infof("%s", reqInfo.toCurl())
-
- }
- if rt.levels[debugRequestHeaders] {
- klog.Infof("Request Headers:")
- for key, values := range reqInfo.RequestHeaders {
- for _, value := range values {
- klog.Infof(" %s: %s", key, value)
- }
- }
- }
-
- startTime := time.Now()
- response, err := rt.delegatedRoundTripper.RoundTrip(req)
- reqInfo.Duration = time.Since(startTime)
-
- reqInfo.complete(response, err)
-
- if rt.levels[debugURLTiming] {
- klog.Infof("%s %s %s in %d milliseconds", reqInfo.RequestVerb, reqInfo.RequestURL, reqInfo.ResponseStatus, reqInfo.Duration.Nanoseconds()/int64(time.Millisecond))
- }
- if rt.levels[debugResponseStatus] {
- klog.Infof("Response Status: %s in %d milliseconds", reqInfo.ResponseStatus, reqInfo.Duration.Nanoseconds()/int64(time.Millisecond))
- }
- if rt.levels[debugResponseHeaders] {
- klog.Infof("Response Headers:")
- for key, values := range reqInfo.ResponseHeaders {
- for _, value := range values {
- klog.Infof(" %s: %s", key, value)
- }
- }
- }
-
- return response, err
-}
-
-func (rt *debuggingRoundTripper) WrappedRoundTripper() http.RoundTripper {
- return rt.delegatedRoundTripper
-}
-
-func legalHeaderByte(b byte) bool {
- return int(b) < len(legalHeaderKeyBytes) && legalHeaderKeyBytes[b]
-}
-
-func shouldEscape(b byte) bool {
- // url.PathUnescape() returns an error if any '%' is not followed by two
- // hexadecimal digits, so we'll intentionally encode it.
- return !legalHeaderByte(b) || b == '%'
-}
-
-func headerKeyEscape(key string) string {
- buf := strings.Builder{}
- for i := 0; i < len(key); i++ {
- b := key[i]
- if shouldEscape(b) {
- // %-encode bytes that should be escaped:
- // https://tools.ietf.org/html/rfc3986#section-2.1
- fmt.Fprintf(&buf, "%%%02X", b)
- continue
- }
- buf.WriteByte(b)
- }
- return buf.String()
-}
-
-// legalHeaderKeyBytes was copied from net/http/lex.go's isTokenTable.
-// See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators
-var legalHeaderKeyBytes = [127]bool{
- '%': true,
- '!': true,
- '#': true,
- '$': true,
- '&': true,
- '\'': true,
- '*': true,
- '+': true,
- '-': true,
- '.': true,
- '0': true,
- '1': true,
- '2': true,
- '3': true,
- '4': true,
- '5': true,
- '6': true,
- '7': true,
- '8': true,
- '9': true,
- 'A': true,
- 'B': true,
- 'C': true,
- 'D': true,
- 'E': true,
- 'F': true,
- 'G': true,
- 'H': true,
- 'I': true,
- 'J': true,
- 'K': true,
- 'L': true,
- 'M': true,
- 'N': true,
- 'O': true,
- 'P': true,
- 'Q': true,
- 'R': true,
- 'S': true,
- 'T': true,
- 'U': true,
- 'W': true,
- 'V': true,
- 'X': true,
- 'Y': true,
- 'Z': true,
- '^': true,
- '_': true,
- '`': true,
- 'a': true,
- 'b': true,
- 'c': true,
- 'd': true,
- 'e': true,
- 'f': true,
- 'g': true,
- 'h': true,
- 'i': true,
- 'j': true,
- 'k': true,
- 'l': true,
- 'm': true,
- 'n': true,
- 'o': true,
- 'p': true,
- 'q': true,
- 'r': true,
- 's': true,
- 't': true,
- 'u': true,
- 'v': true,
- 'w': true,
- 'x': true,
- 'y': true,
- 'z': true,
- '|': true,
- '~': true,
-}