diff --git a/internal/resolver/delegatingresolver/delegatingresolver.go b/internal/resolver/delegatingresolver/delegatingresolver.go index c0e22757727a..20b8fb098ac3 100644 --- a/internal/resolver/delegatingresolver/delegatingresolver.go +++ b/internal/resolver/delegatingresolver/delegatingresolver.go @@ -186,23 +186,15 @@ func (r *delegatingResolver) Close() { r.proxyResolver = nil } -func networkTypeFromAddr(addr resolver.Address) string { - networkType, ok := networktype.Get(addr) - if !ok { - networkType, _ = transport.ParseDialTarget(addr.Addr) - } - return networkType -} - -func isTCPAddressPresent(state *resolver.State) bool { +func needsProxyResolver(state *resolver.State) bool { for _, addr := range state.Addresses { - if networkType := networkTypeFromAddr(addr); networkType == "tcp" { + if !skipProxy(addr) { return true } } for _, endpoint := range state.Endpoints { for _, addr := range endpoint.Addresses { - if networktype := networkTypeFromAddr(addr); networktype == "tcp" { + if !skipProxy(addr) { return true } } @@ -210,6 +202,29 @@ func isTCPAddressPresent(state *resolver.State) bool { return false } +func skipProxy(address resolver.Address) bool { + // Avoid proxy when network is not tcp. + networkType, ok := networktype.Get(address) + if !ok { + networkType, _ = transport.ParseDialTarget(address.Addr) + } + if networkType != "tcp" { + return true + } + + req := &http.Request{URL: &url.URL{ + Scheme: "https", + Host: address.Addr, + }} + // Avoid proxy when address included in `NO_PROXY` environment variable or + // fails to get the proxy address. + url, err := HTTPSProxyFromEnvironment(req) + if err != nil || url == nil { + return true + } + return false +} + // updateClientConnStateLocked constructs a combined list of addresses by // pairing each proxy address with every target address of type TCP. For each // pair, it creates a new [resolver.Address] using the proxy address and @@ -240,8 +255,7 @@ func (r *delegatingResolver) updateClientConnStateLocked() error { } var addresses []resolver.Address for _, targetAddr := range (*r.targetResolverState).Addresses { - // Avoid proxy when network is not tcp. - if networkType := networkTypeFromAddr(targetAddr); networkType != "tcp" { + if skipProxy(targetAddr) { addresses = append(addresses, targetAddr) continue } @@ -259,7 +273,7 @@ func (r *delegatingResolver) updateClientConnStateLocked() error { var addrs []resolver.Address for _, targetAddr := range endpt.Addresses { // Avoid proxy when network is not tcp. - if networkType := networkTypeFromAddr(targetAddr); networkType != "tcp" { + if skipProxy(targetAddr) { addrs = append(addrs, targetAddr) continue } @@ -340,9 +354,10 @@ func (r *delegatingResolver) updateTargetResolverState(state resolver.State) err logger.Infof("Addresses received from target resolver: %v", state.Addresses) } r.targetResolverState = &state - // If no addresses returned by resolver have network type as tcp , do not - // wait for proxy update. - if !isTCPAddressPresent(r.targetResolverState) { + // If all addresses returned by the target resolver have a non-TCP network + // type, or are listed in the `NO_PROXY` environment variable, do not wait + // for proxy update. + if !needsProxyResolver(r.targetResolverState) { return r.cc.UpdateState(*r.targetResolverState) } diff --git a/internal/resolver/delegatingresolver/delegatingresolver_ext_test.go b/internal/resolver/delegatingresolver/delegatingresolver_ext_test.go index b7176d5fbb23..c14d420940d9 100644 --- a/internal/resolver/delegatingresolver/delegatingresolver_ext_test.go +++ b/internal/resolver/delegatingresolver/delegatingresolver_ext_test.go @@ -164,6 +164,19 @@ func proxyAddressWithTargetAttribute(proxyAddr string, targetAddr string) resolv return addr } +func overrideTestHTTPSProxy(t *testing.T, proxyAddr string) { + t.Helper() + hpfe := func(req *http.Request) (*url.URL, error) { + return &url.URL{ + Scheme: "https", + Host: proxyAddr, + }, nil + } + originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment + delegatingresolver.HTTPSProxyFromEnvironment = hpfe + t.Cleanup(func() { delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe }) +} + // Tests the scenario where proxy is configured and the target URI contains the // "dns" scheme and target resolution is enabled. The test verifies that the // addresses returned by the delegating resolver combines the addresses @@ -176,21 +189,8 @@ func (s) TestDelegatingResolverwithDNSAndProxyWithTargetResolution(t *testing.T) envProxyAddr = "proxytest.com" resolvedProxyTestAddr1 = "11.11.11.11:7687" ) - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == targetTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, targetTestAddr) - return nil, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) + // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("dns") target := targetResolver.Scheme() + ":///" + targetTestAddr @@ -257,21 +257,7 @@ func (s) TestDelegatingResolverwithDNSAndProxyWithNoTargetResolution(t *testing. envProxyAddr = "proxytest.com" resolvedProxyTestAddr1 = "11.11.11.11:7687" ) - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == targetTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, targetTestAddr) - return nil, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) targetResolver := manual.NewBuilderWithScheme("dns") target := targetResolver.Scheme() + ":///" + targetTestAddr @@ -323,21 +309,7 @@ func (s) TestDelegatingResolverwithCustomResolverAndProxy(t *testing.T) { envProxyAddr = "proxytest.com" resolvedProxyTestAddr1 = "11.11.11.11:7687" ) - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == targetTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, targetTestAddr) - return nil, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("test") @@ -410,21 +382,7 @@ func (s) TestDelegatingResolverForEndpointsWithProxy(t *testing.T) { resolvedProxyTestAddr1 = "11.11.11.11:7687" resolvedProxyTestAddr2 = "22.22.22.22:7687" ) - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == targetTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, targetTestAddr) - return nil, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("test") @@ -517,21 +475,7 @@ func (s) TestDelegatingResolverForMultipleProxyAddress(t *testing.T) { resolvedProxyTestAddr1 = "11.11.11.11:7687" resolvedProxyTestAddr2 = "22.22.22.22:7687" ) - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == targetTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, targetTestAddr) - return nil, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("test") @@ -598,17 +542,7 @@ func (s) TestDelegatingResolverForMultipleProxyAddress(t *testing.T) { func (s) TestDelegatingResolverUpdateStateDuringClose(t *testing.T) { const envProxyAddr = "proxytest.com" - hpfe := func(req *http.Request) (*url.URL, error) { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("test") @@ -661,9 +595,13 @@ func (s) TestDelegatingResolverUpdateStateDuringClose(t *testing.T) { // Updating the channel will result in an error being returned. Since the // target resolver's Close method is already called, the delegating resolver // must not call "ResolveNow" on it. - go proxyResolver.UpdateState(resolver.State{ - Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, - }) + proxyUpdateCh := make(chan struct{}) + go func() { + proxyResolver.UpdateState(resolver.State{ + Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, + }) + close(proxyUpdateCh) + }() unblockProxyResolverClose <- struct{}{} select { @@ -671,6 +609,15 @@ func (s) TestDelegatingResolverUpdateStateDuringClose(t *testing.T) { t.Fatalf("targetResolver.ResolveNow() called unexpectedly.") case <-time.After(defaultTestShortTimeout): } + // Wait for the proxy update to complete before returning from the test and + // before the deferred reassignment of + // delegatingresolver.HTTPSProxyFromEnvironment. This ensures that we read + // from the function before it is reassigned, preventing a race condition. + select { + case <-proxyUpdateCh: + case <-ctx.Done(): + t.Fatalf("Context timed out waiting for proxyResolver.UpdateState() to be called.") + } } // Tests that calling cc.UpdateState in a blocking manner from a child resolver @@ -682,17 +629,7 @@ func (s) TestDelegatingResolverUpdateStateDuringClose(t *testing.T) { func (s) TestDelegatingResolverUpdateStateFromResolveNow(t *testing.T) { const envProxyAddr = "proxytest.com" - hpfe := func(req *http.Request) (*url.URL, error) { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("test") @@ -746,17 +683,7 @@ func (s) TestDelegatingResolverUpdateStateFromResolveNow(t *testing.T) { func (s) TestDelegatingResolverResolveNow(t *testing.T) { const envProxyAddr = "proxytest.com" - hpfe := func(req *http.Request) (*url.URL, error) { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("test") @@ -827,21 +754,7 @@ func (s) TestDelegatingResolverForNonTCPTarget(t *testing.T) { resolvedTargetTestAddr1 = "1.1.1.1:8080" envProxyAddr = "proxytest.com" ) - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == targetTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, targetTestAddr) - return nil, nil - } - originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { - delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe - }() + overrideTestHTTPSProxy(t, envProxyAddr) // Manual resolver to control the target resolution. targetResolver := manual.NewBuilderWithScheme("test") @@ -893,7 +806,7 @@ func (s) TestDelegatingResolverForNonTCPTarget(t *testing.T) { // Tests the scenario where a proxy is configured, and the resolver returns tcp // and non-tcp addresses. The test verifies that the delegating resolver doesn't -// add proxyatrribute to adresses with network type other than tcp , but adds +// add proxyatrribute to adresses with network type other than tcp, but adds // the proxyattribute to addresses with network type tcp. func (s) TestDelegatingResolverForMixNetworkType(t *testing.T) { const ( @@ -902,15 +815,80 @@ func (s) TestDelegatingResolverForMixNetworkType(t *testing.T) { resolvedTargetTestAddr2 = "2.2.2.2:8080" envProxyAddr = "proxytest.com" ) + overrideTestHTTPSProxy(t, envProxyAddr) + + // Manual resolver to control the target resolution. + targetResolver := manual.NewBuilderWithScheme("test") + target := targetResolver.Scheme() + ":///" + targetTestAddr + // Set up a manual DNS resolver to control the proxy address resolution. + proxyResolver, proxyResolverBuilt := setupDNS(t) + + tcc, stateCh, _ := createTestResolverClientConn(t) + if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { + t.Fatalf("Failed to create delegating resolver: %v", err) + } + // Set network to anything other than tcp. + nonTCPAddr := networktype.Set(resolver.Address{Addr: resolvedTargetTestAddr1}, "unix") + targetResolver.UpdateState(resolver.State{ + Addresses: []resolver.Address{nonTCPAddr, {Addr: resolvedTargetTestAddr2}}, + Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr, {Addr: resolvedTargetTestAddr2}}}}, + ServiceConfig: &serviceconfig.ParseResult{}, + }) + + select { + case <-stateCh: + t.Fatalf("Delegating resolver invoked UpdateState before both the proxy and target resolvers had updated their states.") + case <-time.After(defaultTestShortTimeout): + } + + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + + // Wait for the proxy resolver to be built before calling UpdateState. + mustBuildResolver(ctx, t, proxyResolverBuilt) + proxyResolver.UpdateState(resolver.State{ + Addresses: []resolver.Address{{Addr: envProxyAddr}}, + ServiceConfig: &serviceconfig.ParseResult{}, + }) + + var gotState resolver.State + select { + case gotState = <-stateCh: + case <-ctx.Done(): + t.Fatal("Context timed out when waiting for a state update from the delegating resolver") + } + wantState := resolver.State{ + Addresses: []resolver.Address{nonTCPAddr, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr2)}, + Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr2)}}}, + ServiceConfig: &serviceconfig.ParseResult{}, + } + + if diff := cmp.Diff(gotState, wantState); diff != "" { + t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) + } +} + +// Tests the scenario where a proxy is configured but some addresses are +// excluded (by using the NO_PROXY environment variable). The test verifies that +// the delegating resolver doesn't add proxyatrribute to adresses excluded, but +// adds the proxyattribute to all other addresses. +func (s) TestDelegatingResolverWithNoProxyEnvUsed(t *testing.T) { + const ( + targetTestAddr = "test.target" + noproxyresolvedTargetAddr = "1.1.1.1:8080" + resolvedTargetTestAddr = "2.2.2.2:8080" + envProxyAddr = "proxytest.com" + ) hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == targetTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil + // return nil to mimick the scenario where the address is excluded using + // `NO_PROXY` env variable. + if req.URL.Host == noproxyresolvedTargetAddr { + return nil, nil } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, targetTestAddr) - return nil, nil + return &url.URL{ + Scheme: "https", + Host: envProxyAddr, + }, nil } originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment delegatingresolver.HTTPSProxyFromEnvironment = hpfe @@ -928,11 +906,10 @@ func (s) TestDelegatingResolverForMixNetworkType(t *testing.T) { if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { t.Fatalf("Failed to create delegating resolver: %v", err) } - // Set network to anything other than tcp. - nonTCPAddr := networktype.Set(resolver.Address{Addr: resolvedTargetTestAddr1}, "unix") + targetResolver.UpdateState(resolver.State{ - Addresses: []resolver.Address{nonTCPAddr, {Addr: resolvedTargetTestAddr2}}, - Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr, {Addr: resolvedTargetTestAddr2}}}}, + Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, {Addr: resolvedTargetTestAddr}}, + Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, {Addr: resolvedTargetTestAddr}}}}, ServiceConfig: &serviceconfig.ParseResult{}, }) @@ -959,8 +936,8 @@ func (s) TestDelegatingResolverForMixNetworkType(t *testing.T) { t.Fatal("Context timed out when waiting for a state update from the delegating resolver") } wantState := resolver.State{ - Addresses: []resolver.Address{nonTCPAddr, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr2)}, - Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr2)}}}, + Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr)}, + Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr)}}}, ServiceConfig: &serviceconfig.ParseResult{}, } diff --git a/internal/transport/proxy_ext_test.go b/internal/transport/proxy_ext_test.go index 4f5ece1e81a2..6359796ffb12 100644 --- a/internal/transport/proxy_ext_test.go +++ b/internal/transport/proxy_ext_test.go @@ -71,6 +71,19 @@ func isIPAddr(addr string) bool { return err == nil } +func overrideTestHTTPSProxy(t *testing.T, proxyAddr string) { + t.Helper() + hpfe := func(req *http.Request) (*url.URL, error) { + return &url.URL{ + Scheme: "https", + Host: proxyAddr, + }, nil + } + originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment + delegatingresolver.HTTPSProxyFromEnvironment = hpfe + t.Cleanup(func() { delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe }) +} + // Tests the scenario where grpc.Dial is performed using a proxy with the // default resolver in the target URI. The test verifies that the connection is // established to the proxy server, sends the unresolved target URI in the HTTP @@ -86,7 +99,7 @@ func (s) TestGRPCDialWithProxy(t *testing.T) { t.Error(err) } if got, want := host, "localhost"; got != want { - t.Errorf(" Unexpected request host: %s , want = %s ", got, want) + t.Errorf(" Unexpected request host: %s, want = %s ", got, want) } } pServer := proxyserver.New(t, reqCheck, false) @@ -95,20 +108,7 @@ func (s) TestGRPCDialWithProxy(t *testing.T) { // correctly even when unresolved. pAddr := fmt.Sprintf("localhost:%d", testutils.ParsePort(t, pServer.Addr)) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == unresolvedTargetURI { - return &url.URL{ - Scheme: "https", - Host: pAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, unresolvedTargetURI) - return nil, nil - } - orighpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { delegatingresolver.HTTPSProxyFromEnvironment = orighpfe }() + overrideTestHTTPSProxy(t, pAddr) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() @@ -152,20 +152,7 @@ func (s) TestGRPCDialWithDNSAndProxy(t *testing.T) { } pServer := proxyserver.New(t, reqCheck, false) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == unresolvedTargetURI { - return &url.URL{ - Scheme: "https", - Host: pServer.Addr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, unresolvedTargetURI) - return nil, nil - } - orighpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { delegatingresolver.HTTPSProxyFromEnvironment = orighpfe }() + overrideTestHTTPSProxy(t, pServer.Addr) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() @@ -202,7 +189,7 @@ func (s) TestNewClientWithProxy(t *testing.T) { t.Error(err) } if got, want := host, "localhost"; got != want { - t.Errorf(" Unexpected request host: %s , want = %s ", got, want) + t.Errorf(" Unexpected request host: %s, want = %s ", got, want) } } pServer := proxyserver.New(t, reqCheck, false) @@ -211,20 +198,7 @@ func (s) TestNewClientWithProxy(t *testing.T) { // correctly even when unresolved. pAddr := fmt.Sprintf("localhost:%d", testutils.ParsePort(t, pServer.Addr)) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == unresolvedTargetURI { - return &url.URL{ - Scheme: "https", - Host: pAddr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, unresolvedTargetURI) - return nil, nil - } - orighpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { delegatingresolver.HTTPSProxyFromEnvironment = orighpfe }() + overrideTestHTTPSProxy(t, pAddr) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() @@ -265,20 +239,7 @@ func (s) TestNewClientWithProxyAndCustomResolver(t *testing.T) { } pServer := proxyserver.New(t, reqCheck, false) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == unresolvedTargetURI { - return &url.URL{ - Scheme: "https", - Host: pServer.Addr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, unresolvedTargetURI) - return nil, nil - } - orighpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { delegatingresolver.HTTPSProxyFromEnvironment = orighpfe }() + overrideTestHTTPSProxy(t, pServer.Addr) // Create and update a custom resolver for target URI. targetResolver := manual.NewBuilderWithScheme("test") @@ -327,20 +288,7 @@ func (s) TestNewClientWithProxyAndTargetResolutionEnabled(t *testing.T) { } pServer := proxyserver.New(t, reqCheck, false) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == unresolvedTargetURI { - return &url.URL{ - Scheme: "https", - Host: pServer.Addr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, unresolvedTargetURI) - return nil, nil - } - orighpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { delegatingresolver.HTTPSProxyFromEnvironment = orighpfe }() + overrideTestHTTPSProxy(t, pServer.Addr) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() @@ -372,20 +320,7 @@ func (s) TestNewClientWithNoProxy(t *testing.T) { reqCheck := func(_ *http.Request) { t.Error("proxy server should not have received a Connect request") } pServer := proxyserver.New(t, reqCheck, false) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == unresolvedTargetURI { - return &url.URL{ - Scheme: "https", - Host: pServer.Addr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, unresolvedTargetURI) - return nil, nil - } - orighpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { delegatingresolver.HTTPSProxyFromEnvironment = orighpfe }() + overrideTestHTTPSProxy(t, pServer.Addr) dopts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -417,20 +352,7 @@ func (s) TestNewClientWithContextDialer(t *testing.T) { reqCheck := func(_ *http.Request) { t.Error("proxy server should not have received a Connect request") } pServer := proxyserver.New(t, reqCheck, false) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == unresolvedTargetURI { - return &url.URL{ - Scheme: "https", - Host: pServer.Addr, - }, nil - } - t.Errorf("Unexpected request host to proxy: %s want %s", req.URL.Host, unresolvedTargetURI) - return nil, nil - } - orighpfe := delegatingresolver.HTTPSProxyFromEnvironment - delegatingresolver.HTTPSProxyFromEnvironment = hpfe - defer func() { delegatingresolver.HTTPSProxyFromEnvironment = orighpfe }() + overrideTestHTTPSProxy(t, pServer.Addr) // Create a custom dialer that directly dials the backend. customDialer := func(_ context.Context, unresolvedTargetURI string) (net.Conn, error) { @@ -472,7 +394,7 @@ func (s) TestBasicAuthInNewClientWithProxy(t *testing.T) { reqCheck := func(req *http.Request) { proxyCalled = true if got, want := req.URL.Host, "example.test"; got != want { - t.Errorf(" Unexpected request host: %s , want = %s ", got, want) + t.Errorf(" Unexpected request host: %s, want = %s ", got, want) } wantProxyAuthStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+password)) if got := req.Header.Get("Proxy-Authorization"); got != wantProxyAuthStr {