forwarder
forwarder copied to clipboard
martian: allow to use http2 connection to upstream
Upstream requests don't interact well with Transport: connections could always be reused, but Transport thinks they go to different Hosts, so it spawns tons of useless connections. Just use dialContext, which will multiplex via single connection, if http/2.
Currently the http/2 proxy is not supported in http.Transport https://github.com/golang/go/issues/26479. However, it can be worked around by a custom transport that manages http2 connections.
In a simplified case of a single upstream proxy it would be sufficient to have a http2.ClientConn to the proxy passed to Martian as a http.RoundTripper. The more complete solution is to have http2.Transport with a custom connection pool and manage connection lifecycle i.e. dial connections when needed.
Another example of similar, but different, approach can be github.com/caddyserver/forwardproxy/httpclient. There for each request we establish new CONNECT tunnel over http2 stream. This solution does not work well with proxy chaining and only works for http1 backends. The last proxy enters the CONNECT path and it's difficult to coordinate.
One thing to note is not to use the http2 conn if the handling with connection upgrade.
https://github.com/kubernetes/kubernetes/pull/88781/files#diff-09ebe223122bee0cad4dde23b1c6b36ea2e30fe45e25ca4cd2e04b32a13948d6
Another thing to note is that this approach can be used to elegantly implement #99.