client-go wrapTransport

发送请求前,支持修改请求内容或者拦截。
发送请求后,支持修改响应内容或者拦截。

结构体实例实现

package main

import (
	"context"
	"fmt"
	"net/http"

	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

type customRoundTripper struct {
	rt http.RoundTripper
}

// customRoundTripper 实现了 http.RoundTripper 接口
func (crt *customRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	// 在请求发送前增加自定义逻辑
	req.Header.Add("a", "b")
	fmt.Println("add header a/b")

	resp, err := crt.rt.RoundTrip(req)
	if err != nil {
		return nil, err
	}
	// 在请求响应后打印
	fmt.Println("response success")

	return resp, nil
}

func main() {
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		fmt.Println(err)
		return
	}

	// 传输层走customRoundTripper
	config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
		return &customRoundTripper{rt: rt}
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	_, err = clientset.CoreV1().Namespaces().List(context.Background(), v1.ListOptions{})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("list namespaces success")
}

匿名函数实例实现

package main

import (
	"context"
	"fmt"
	"net/http"

	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

type RoundTripAnonymousFunctionImpl func(req *http.Request) (*http.Response, error)

// RoundTripAnonymousFunctionImpl 实现了 http.RoundTripper 接口
func (r RoundTripAnonymousFunctionImpl) RoundTrip(req *http.Request) (*http.Response, error) {
	return r(req)
}

func main() {
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		fmt.Println(err)
		return
	}

	// 传输层走RoundTripAnonymousFunctionImpl
	config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
		return RoundTripAnonymousFunctionImpl(func(req *http.Request) (*http.Response, error) {
			// 在请求发送前增加自定义逻辑
			req.Header.Add("a", "b")
			fmt.Println("add header a/b")

			resp, err := rt.RoundTrip(req)
			if err != nil {
				return nil, err
			}
			// 在请求响应后打印
			fmt.Println("response success")

			return resp, nil
		})
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	_, err = clientset.CoreV1().Namespaces().List(context.Background(), v1.ListOptions{})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("list namespaces success")
}

kube-apiserver请求带上requestID

package main

import (
	"context"
	"fmt"
	"net/http"

	"github.com/google/uuid"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

const headerRequestIDKey = "request_id"

type ctxRequestIDKey struct{}

type customRoundTripper struct {
	rt http.RoundTripper
}

// customRoundTripper 实现了 http.RoundTripper 接口
func (crt *customRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	// 设置ctxRequestIDKey
	requestID, _ := req.Context().Value(ctxRequestIDKey{}).(string)
	// 发出请求前打印requestID
	fmt.Printf("req requestID: %s\n", requestID)
	req.Header[headerRequestIDKey] = []string{requestID}

	resp, err := crt.rt.RoundTrip(req)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func main() {
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		fmt.Println(err)
		return
	}

	// 传输层走customRoundTripper
	config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
		return &customRoundTripper{rt: rt}
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	uuidStr := uuid.NewString()
	ctx := context.WithValue(context.Background(), ctxRequestIDKey{}, uuidStr)
	_, err = clientset.CoreV1().Namespaces().List(ctx, v1.ListOptions{})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("list namespaces success")
}

在go http NewRequestWithContext方法中,用户传入的context key/value值保存到request的context。虽然response包含了request,但是response中是全新的request,没有requestID。

posted on 2025-03-22 20:10  王景迁  阅读(24)  评论(0)    收藏  举报

导航