New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disable HTTP2 while proxying a "Connection: upgrade" request #88781
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,12 @@ import ( | |
"k8s.io/apimachinery/third_party/forked/golang/netutil" | ||
) | ||
|
||
func DialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (net.Conn, error) { | ||
// dialURL will dial the specified URL using the underlying dialer held by the passed | ||
// RoundTripper. The primary use of this method is to support proxying upgradable connections. | ||
// For this reason this method will prefer to negotiate http/1.1 if the URL scheme is https. | ||
// If you wish to ensure ALPN negotiates http2 then set NextProto=[]string{"http2"} in the | ||
// TLSConfig of the http.Transport | ||
func dialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (net.Conn, error) { | ||
dialAddr := netutil.CanonicalAddr(url) | ||
|
||
dialer, err := utilnet.DialerFor(transport) | ||
|
@@ -81,6 +86,15 @@ func DialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (ne | |
tlsConfigCopy.ServerName = inferredHost | ||
tlsConfig = tlsConfigCopy | ||
} | ||
|
||
// Since this method is primary used within a "Connection: Upgrade" call we assume the caller is | ||
// going to write HTTP/1.1 request to the wire. http2 should not be allowed in the TLSConfig.NextProtos, | ||
// so we explicitly set that here. We only do this check if the TLSConfig support http/1.1. | ||
if supportsHTTP11(tlsConfig.NextProtos) { | ||
tlsConfig = tlsConfig.Clone() | ||
tlsConfig.NextProtos = []string{"http/1.1"} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The above block tries hard not to modify the tlsConfig that is passed in. Do we need to make a copy here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're correct, I thought it was already copied or new at this point but I see I'm wrong. |
||
} | ||
|
||
tlsConn = tls.Client(netConn, tlsConfig) | ||
if err := tlsConn.Handshake(); err != nil { | ||
netConn.Close() | ||
|
@@ -115,3 +129,15 @@ func DialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (ne | |
return nil, fmt.Errorf("Unknown scheme: %s", url.Scheme) | ||
} | ||
} | ||
|
||
func supportsHTTP11(nextProtos []string) bool { | ||
if len(nextProtos) == 0 { | ||
return true | ||
} | ||
for _, proto := range nextProtos { | ||
if proto == "http/1.1" { | ||
return true | ||
} | ||
} | ||
return false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does "Connection: Upgrade" mean? Is it a term?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://tools.ietf.org/html/rfc7230#section-6.7
We upgrade http requests to websocket or spdy for streaming request like exec and logs. The headers communicates that you are switching protocols from http1/1 to X so when the upgrade is complete you can send whatever over it like it's just a tcp connection. Sending an upgrade request over http/2 is a connection error because underlying tcp connections are shared between requests. We can eventually migrate off of http1/1 altogether but we are waiting for go support to land. golang/go#27244 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. It's an http header.
nit: should be "Connection: upgrade" according to the RFC.