github.com/oam-dev/cluster-gateway@v1.9.0/pkg/apis/cluster/transport/roundtripper.go (about) 1 package multicluster 2 3 import ( 4 "fmt" 5 "net/http" 6 "strings" 7 8 "github.com/oam-dev/cluster-gateway/pkg/config" 9 ) 10 11 var _ http.RoundTripper = &clusterGatewayRoundTripper{} 12 13 type clusterGatewayRoundTripper struct { 14 delegate http.RoundTripper 15 // falling back to the hosting cluster 16 // this is required when the client does implicit api discovery 17 // e.g. controller-runtime client 18 fallback bool 19 } 20 21 func NewClusterGatewayRoundTripper(delegate http.RoundTripper) http.RoundTripper { 22 return &clusterGatewayRoundTripper{ 23 delegate: delegate, 24 fallback: true, 25 } 26 } 27 28 func NewStrictClusterGatewayRoundTripper(delegate http.RoundTripper, fallback bool) http.RoundTripper { 29 return &clusterGatewayRoundTripper{ 30 delegate: delegate, 31 fallback: false, 32 } 33 } 34 35 func (c *clusterGatewayRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) { 36 clusterName, exists := GetMultiClusterContext(request.Context()) 37 if !exists { 38 if !c.fallback { 39 return nil, fmt.Errorf("missing cluster name in the request context") 40 } 41 return c.delegate.RoundTrip(request) 42 } 43 request.URL.Path = formatProxyURL(clusterName, request.URL.Path) 44 return c.delegate.RoundTrip(request) 45 } 46 47 func formatProxyURL(clusterName, originalPath string) string { 48 originalPath = strings.TrimPrefix(originalPath, "/") 49 return strings.Join([]string{ 50 "/apis", 51 config.MetaApiGroupName, 52 config.MetaApiVersionName, 53 "clustergateways", 54 clusterName, 55 "proxy", 56 originalPath}, "/") 57 }