Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions lambda/api_client_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,42 @@ func TestExtensionAPIClientBypassesProxy(t *testing.T) {
proxy := proxyForClient(t, client, nonLoopbackAPIRequest(t))
require.Nil(t, proxy, "Extensions API client must not route through the configured proxy, got %v", proxy)
}

// wrappedRoundTripper is a RoundTripper that is not an *http.Transport, mirroring
// how instrumentation libraries (for example otelhttp) replace http.DefaultTransport.
type wrappedRoundTripper struct {
base http.RoundTripper
}

func (w *wrappedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
return w.base.RoundTrip(req)
}

// When http.DefaultTransport is a non-*http.Transport wrapper, constructing the
// clients must not panic on a type assertion, and the transport must still bypass
// the proxy.
func TestAPIClientsWithWrappedDefaultTransport(t *testing.T) {
t.Setenv("HTTP_PROXY", "http://192.0.2.100:3128")
t.Setenv("HTTPS_PROXY", "http://192.0.2.100:3128")
t.Setenv("http_proxy", "http://192.0.2.100:3128")
t.Setenv("https_proxy", "http://192.0.2.100:3128")

original := http.DefaultTransport
t.Cleanup(func() { http.DefaultTransport = original })
http.DefaultTransport = &wrappedRoundTripper{base: original}

for _, tc := range []struct {
name string
client func() *http.Client
}{
{"runtime", func() *http.Client { return newRuntimeAPIClient("192.0.2.1:9001").httpClient }},
{"extension", func() *http.Client { return newExtensionAPIClient("192.0.2.1:9001").httpClient }},
} {
t.Run(tc.name, func(t *testing.T) {
var client *http.Client
require.NotPanics(t, func() { client = tc.client() })
proxy := proxyForClient(t, client, nonLoopbackAPIRequest(t))
require.Nil(t, proxy, "%s API client must not route through the configured proxy, got %v", tc.name, proxy)
})
}
}
7 changes: 6 additions & 1 deletion lambda/runtime_api_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ type runtimeAPIClient struct {
// newAPITransport returns an HTTP transport that never proxies, so calls to the
// link-local Runtime/Extensions API bypass any customer-configured proxy.
func newAPITransport() *http.Transport {
transport := http.DefaultTransport.(*http.Transport).Clone()
transport, ok := http.DefaultTransport.(*http.Transport)
if ok {
transport = transport.Clone()
} else {
transport = &http.Transport{}
}
transport.Proxy = nil
return transport
}
Expand Down
Loading