mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
ipn/ipnlocal: initiate proxy transport once (#9883)
Initiates http/h2c transport for userspace proxy backend lazily and at most once. Updates tailscale/tailscale#9725 Signed-off-by: Irbe Krumina <irbe@tailscale.com>
This commit is contained in:
parent
73bbf941f8
commit
f09cb45f9d
@ -31,6 +31,7 @@
|
||||
"tailscale.com/net/netutil"
|
||||
"tailscale.com/syncs"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/lazy"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/util/mak"
|
||||
"tailscale.com/version"
|
||||
@ -568,6 +569,10 @@ type reverseProxy struct {
|
||||
insecure bool
|
||||
backend string
|
||||
lb *LocalBackend
|
||||
// transport for non-h2c backends
|
||||
httpTransport lazy.SyncValue[http.RoundTripper]
|
||||
// transport for h2c backends
|
||||
h2cTransport lazy.SyncValue[http.RoundTripper]
|
||||
}
|
||||
|
||||
func (rp *reverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
@ -586,15 +591,19 @@ func (rp *reverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// gRPC to fix a known problem pf plaintext gRPC backends
|
||||
if rp.shouldProxyViaH2C(r) {
|
||||
rp.logf("received a proxy request for plaintext gRPC")
|
||||
p.Transport = &http2.Transport{
|
||||
AllowHTTP: true,
|
||||
DialTLSContext: func(ctx context.Context, network string, addr string, _ *tls.Config) (net.Conn, error) {
|
||||
return rp.lb.dialer.SystemDial(ctx, "tcp", rp.url.Host)
|
||||
},
|
||||
}
|
||||
|
||||
p.Transport = rp.getH2CTransport()
|
||||
} else {
|
||||
p.Transport = &http.Transport{
|
||||
p.Transport = rp.getTransport()
|
||||
}
|
||||
p.ServeHTTP(w, r)
|
||||
|
||||
}
|
||||
|
||||
// getTransport gets transport for http backends. Transport gets created lazily
|
||||
// at most once.
|
||||
func (rp *reverseProxy) getTransport() http.RoundTripper {
|
||||
return rp.httpTransport.Get(func() http.RoundTripper {
|
||||
return &http.Transport{
|
||||
DialContext: rp.lb.dialer.SystemDial,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: rp.insecure,
|
||||
@ -606,9 +615,20 @@ func (rp *reverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
}
|
||||
p.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// getH2CTranport gets transport for h2c backends. Creates it lazily at most
|
||||
// once.
|
||||
func (rp *reverseProxy) getH2CTransport() http.RoundTripper {
|
||||
return rp.h2cTransport.Get(func() http.RoundTripper {
|
||||
return &http2.Transport{
|
||||
AllowHTTP: true,
|
||||
DialTLSContext: func(ctx context.Context, network string, addr string, _ *tls.Config) (net.Conn, error) {
|
||||
return rp.lb.dialer.SystemDial(ctx, "tcp", rp.url.Host)
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// This is not a generally reliable way how to determine whether a request is
|
||||
@ -625,7 +645,7 @@ func (rp *reverseProxy) shouldProxyViaH2C(r *http.Request) bool {
|
||||
// https://github.com/grpc/grpc-go/blob/v1.60.0-dev/internal/grpcutil/method.go#L41-L78
|
||||
func isGRPCContentType(contentType string) bool {
|
||||
s, ok := strings.CutPrefix(contentType, grpcBaseContentType)
|
||||
return ok && len(s) == 0 || s[0] == '+' || s[0] == ';'
|
||||
return ok && (len(s) == 0 || s[0] == '+' || s[0] == ';')
|
||||
}
|
||||
|
||||
func addProxyForwardedHeaders(r *httputil.ProxyRequest) {
|
||||
|
@ -614,6 +614,9 @@ func Test_isGRPCContentType(t *testing.T) {
|
||||
"foobar": {
|
||||
contentType: "foobar",
|
||||
},
|
||||
"no content type": {
|
||||
contentType: "",
|
||||
},
|
||||
}
|
||||
for name, scenario := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user