mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Merge pull request #97385 from FabianKramm/fix-http2-proxy
kubectl proxy: override request host
This commit is contained in:
commit
49e0c4456d
@ -74,6 +74,12 @@ type UpgradeAwareHandler struct {
|
||||
RequireSameHostRedirects bool
|
||||
// UseRequestLocation will use the incoming request URL when talking to the backend server.
|
||||
UseRequestLocation bool
|
||||
// UseLocationHost overrides the HTTP host header in requests to the backend server to use the Host from Location.
|
||||
// This will override the req.Host field of a request, while UseRequestLocation will override the req.URL field
|
||||
// of a request. The req.URL.Host specifies the server to connect to, while the req.Host field
|
||||
// specifies the Host header value to send in the HTTP request. If this is false, the incoming req.Host header will
|
||||
// just be forwarded to the backend server.
|
||||
UseLocationHost bool
|
||||
// FlushInterval controls how often the standard HTTP proxy will flush content from the upstream.
|
||||
FlushInterval time.Duration
|
||||
// MaxBytesPerSec controls the maximum rate for an upstream connection. No rate is imposed if the value is zero.
|
||||
@ -227,6 +233,11 @@ func (h *UpgradeAwareHandler) ServeHTTP(w http.ResponseWriter, req *http.Request
|
||||
if !h.UseRequestLocation {
|
||||
newReq.URL = &loc
|
||||
}
|
||||
if h.UseLocationHost {
|
||||
// exchanging req.Host with the backend location is necessary for backends that act on the HTTP host header (e.g. API gateways),
|
||||
// because req.Host has preference over req.URL.Host in filling this header field
|
||||
newReq.Host = h.Location.Host
|
||||
}
|
||||
|
||||
proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme: h.Location.Scheme, Host: h.Location.Host})
|
||||
proxy.Transport = h.Transport
|
||||
@ -282,6 +293,9 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
|
||||
backendConn, rawResponse, err = utilnet.ConnectWithRedirects(req.Method, &location, clone.Header, req.Body, utilnet.DialerFunc(h.DialForUpgrade), h.RequireSameHostRedirects)
|
||||
} else {
|
||||
klog.V(6).Infof("Connecting to backend proxy (direct dial) %s\n Headers: %v", &location, clone.Header)
|
||||
if h.UseLocationHost {
|
||||
clone.Host = h.Location.Host
|
||||
}
|
||||
clone.URL = &location
|
||||
backendConn, err = h.DialForUpgrade(clone)
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ func (fakeConn) SetWriteDeadline(t time.Time) error { return nil }
|
||||
|
||||
type SimpleBackendHandler struct {
|
||||
requestURL url.URL
|
||||
requestHost string
|
||||
requestHeader http.Header
|
||||
requestBody []byte
|
||||
requestMethod string
|
||||
@ -95,6 +96,7 @@ type SimpleBackendHandler struct {
|
||||
|
||||
func (s *SimpleBackendHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
s.requestURL = *req.URL
|
||||
s.requestHost = req.Host
|
||||
s.requestHeader = req.Header
|
||||
s.requestMethod = req.Method
|
||||
var err error
|
||||
@ -162,6 +164,7 @@ func TestServeHTTP(t *testing.T) {
|
||||
notExpectedRespHeader []string
|
||||
upgradeRequired bool
|
||||
expectError func(err error) bool
|
||||
useLocationHost bool
|
||||
}{
|
||||
{
|
||||
name: "root path, simple get",
|
||||
@ -222,6 +225,27 @@ func TestServeHTTP(t *testing.T) {
|
||||
"Access-Control-Allow-Methods",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "use location host",
|
||||
method: "GET",
|
||||
requestPath: "/some/path",
|
||||
expectedPath: "/some/path",
|
||||
useLocationHost: true,
|
||||
},
|
||||
{
|
||||
name: "use location host - invalid upgrade",
|
||||
method: "GET",
|
||||
upgradeRequired: true,
|
||||
requestHeader: map[string]string{
|
||||
httpstream.HeaderConnection: httpstream.HeaderUpgrade,
|
||||
},
|
||||
expectError: func(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "invalid upgrade response: status code 200")
|
||||
},
|
||||
requestPath: "/some/path",
|
||||
expectedPath: "/some/path",
|
||||
useLocationHost: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
@ -244,6 +268,7 @@ func TestServeHTTP(t *testing.T) {
|
||||
backendURL, _ := url.Parse(backendServer.URL)
|
||||
backendURL.Path = test.requestPath
|
||||
proxyHandler := NewUpgradeAwareHandler(backendURL, nil, false, test.upgradeRequired, responder)
|
||||
proxyHandler.UseLocationHost = test.useLocationHost
|
||||
proxyServer := httptest.NewServer(proxyHandler)
|
||||
defer proxyServer.Close()
|
||||
proxyURL, _ := url.Parse(proxyServer.URL)
|
||||
@ -274,6 +299,13 @@ func TestServeHTTP(t *testing.T) {
|
||||
t.Errorf("Error from proxy request: %v", err)
|
||||
}
|
||||
|
||||
// Host
|
||||
if test.useLocationHost && backendHandler.requestHost != backendURL.Host {
|
||||
t.Errorf("Unexpected request host: %s", backendHandler.requestHost)
|
||||
} else if !test.useLocationHost && backendHandler.requestHost == backendURL.Host {
|
||||
t.Errorf("Unexpected request host: %s", backendHandler.requestHost)
|
||||
}
|
||||
|
||||
if test.expectError != nil {
|
||||
if !responder.called {
|
||||
t.Errorf("%d: responder was not invoked", i)
|
||||
|
@ -211,6 +211,7 @@ func NewProxyHandler(apiProxyPrefix string, filter *FilterServer, cfg *rest.Conf
|
||||
proxy := proxy.NewUpgradeAwareHandler(target, transport, false, false, responder)
|
||||
proxy.UpgradeTransport = upgradeTransport
|
||||
proxy.UseRequestLocation = true
|
||||
proxy.UseLocationHost = true
|
||||
|
||||
proxyServer := http.Handler(proxy)
|
||||
if filter != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user