Skip to content

Commit 878630a

Browse files
committed
Pass context to NewHTTPClient for Desktop proxy detection
Assisted-By: docker-agent
1 parent 49f274a commit 878630a

13 files changed

Lines changed: 35 additions & 44 deletions

File tree

pkg/config/sources.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func (a urlSource) Read(ctx context.Context) ([]byte, error) {
229229
// Add GitHub token authorization for GitHub URLs
230230
a.addGitHubAuth(ctx, req)
231231

232-
resp, err := httpclient.NewHTTPClient().Do(req)
232+
resp, err := httpclient.NewHTTPClient(ctx).Do(req)
233233
if err != nil {
234234
// Network error - try to use cached version
235235
if cachedData, cacheErr := os.ReadFile(cachePath); cacheErr == nil {

pkg/desktop/socket/dial_unix.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
package socket
44

55
import (
6+
"context"
67
"net"
78
)
89

910
// DialUnix is a simple wrapper for `net.Dial("unix")`.
10-
func DialUnix(path string) (net.Conn, error) {
11-
return net.DialUnix("unix", nil, &net.UnixAddr{Name: stripUnixScheme(path), Net: "unix"})
11+
func DialUnix(ctx context.Context, path string) (net.Conn, error) {
12+
dialer := &net.Dialer{}
13+
return dialer.DialContext(ctx, "unix", stripUnixScheme(path))
1214
}

pkg/desktop/socket/dial_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import (
1111

1212
// DialUnix is a simple wrapper for `winio.DialPipe(path, 10s)`.
1313
// It provides API compatibility for named pipes with the Unix domain socket API.
14-
func DialUnix(path string) (net.Conn, error) {
15-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
14+
func DialUnix(ctx context.Context, path string) (net.Conn, error) {
15+
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
1616
defer cancel()
1717

1818
if strings.HasPrefix(path, "unix://") {

pkg/httpclient/client.go

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ import (
44
"context"
55
"fmt"
66
"maps"
7-
"net"
87
"net/http"
98
"net/url"
109
"runtime"
1110

12-
"github.com/docker/docker-agent/pkg/desktop"
13-
socket "github.com/docker/docker-agent/pkg/desktop/socket"
11+
"github.com/docker/docker-agent/pkg/remote"
1412
"github.com/docker/docker-agent/pkg/version"
1513
)
1614

@@ -21,7 +19,7 @@ type HTTPOptions struct {
2119

2220
type Opt func(*HTTPOptions)
2321

24-
func NewHTTPClient(opts ...Opt) *http.Client {
22+
func NewHTTPClient(ctx context.Context, opts ...Opt) *http.Client {
2523
httpOptions := HTTPOptions{
2624
Header: make(http.Header),
2725
}
@@ -36,7 +34,7 @@ func NewHTTPClient(opts ...Opt) *http.Client {
3634
// Disable automatic gzip: Go's default transport transparently compresses
3735
// and decompresses responses, which is incompatible with SSE streaming.
3836
// See https://github.com/docker/docker-agent/issues/1956
39-
rt := newTransport()
37+
rt := newTransport(ctx)
4038

4139
return &http.Client{
4240
Transport: &userAgentTransport{
@@ -100,26 +98,17 @@ func WithQuery(query url.Values) Opt {
10098
}
10199

102100
// newTransport returns an HTTP transport with automatic gzip compression disabled and using Docker Desktop proxy if available.
103-
func newTransport() http.RoundTripper {
104-
t, ok := http.DefaultTransport.(*http.Transport)
105-
if !ok {
106-
return http.DefaultTransport
101+
func newTransport(ctx context.Context) http.RoundTripper {
102+
// Get the base transport with Desktop proxy support from remote package
103+
rt := remote.NewTransport(ctx)
104+
105+
// If it's an http.Transport, disable compression for SSE streaming compatibility
106+
if transport, ok := rt.(*http.Transport); ok {
107+
transport.DisableCompression = true
108+
return transport
107109
}
108-
transport := t.Clone()
109-
110-
if desktop.IsDockerDesktopRunning(context.Background()) {
111-
// Route all traffic through Docker Desktop's HTTP proxy socket
112-
// Set a dummy proxy URL - the actual connection happens via DialContext
113-
transport.Proxy = http.ProxyURL(&url.URL{
114-
Scheme: "http",
115-
})
116-
// Override the dialer to connect to the Unix socket for the proxy
117-
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
118-
return socket.DialUnix(desktop.Paths().ProxySocket)
119-
}
120-
}
121-
transport.DisableCompression = true
122-
return transport
110+
111+
return rt
123112
}
124113

125114
type userAgentTransport struct {

pkg/httpclient/client_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func doRequest(t *testing.T, opts ...Opt) http.Header {
7575
}))
7676
defer srv.Close()
7777

78-
client := NewHTTPClient(opts...)
78+
client := NewHTTPClient(t.Context(), opts...)
7979
req, err := http.NewRequest(http.MethodGet, srv.URL, http.NoBody)
8080
require.NoError(t, err)
8181

pkg/model/provider/anthropic/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ func NewClient(ctx context.Context, cfg *latest.ModelConfig, env environment.Pro
163163
slog.Debug("Anthropic API key found, creating client")
164164
requestOptions := []option.RequestOption{
165165
option.WithAPIKey(authToken),
166-
option.WithHTTPClient(httpclient.NewHTTPClient()),
166+
option.WithHTTPClient(httpclient.NewHTTPClient(ctx)),
167167
}
168168
if cfg.BaseURL != "" {
169169
requestOptions = append(requestOptions, option.WithBaseURL(cfg.BaseURL))
@@ -210,7 +210,7 @@ func NewClient(ctx context.Context, cfg *latest.ModelConfig, env environment.Pro
210210
option.WithAuthToken(authToken),
211211
option.WithAPIKey(authToken),
212212
option.WithBaseURL(baseURL),
213-
option.WithHTTPClient(httpclient.NewHTTPClient(httpOptions...)),
213+
option.WithHTTPClient(httpclient.NewHTTPClient(ctx, httpOptions...)),
214214
)
215215

216216
return client, nil

pkg/model/provider/gemini/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func NewClient(ctx context.Context, cfg *latest.ModelConfig, env environment.Pro
9797
}
9898

9999
backend = genai.BackendGeminiAPI
100-
httpClient = httpclient.NewHTTPClient()
100+
httpClient = httpclient.NewHTTPClient(ctx)
101101
}
102102

103103
client, err := genai.NewClient(ctx, &genai.ClientConfig{
@@ -152,7 +152,7 @@ func NewClient(ctx context.Context, cfg *latest.ModelConfig, env environment.Pro
152152
return genai.NewClient(ctx, &genai.ClientConfig{
153153
APIKey: authToken,
154154
Backend: genai.BackendGeminiAPI,
155-
HTTPClient: httpclient.NewHTTPClient(httpOptions...),
155+
HTTPClient: httpclient.NewHTTPClient(ctx, httpOptions...),
156156
HTTPOptions: genai.HTTPOptions{
157157
BaseURL: baseURL,
158158
Headers: http.Header{

pkg/model/provider/openai/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func NewClient(ctx context.Context, cfg *latest.ModelConfig, env environment.Pro
9292
clientOptions = append(clientOptions, option.WithBaseURL(cfg.BaseURL))
9393
}
9494

95-
httpClient := httpclient.NewHTTPClient()
95+
httpClient := httpclient.NewHTTPClient(ctx)
9696
clientOptions = append(clientOptions, option.WithHTTPClient(httpClient))
9797

9898
client := openai.NewClient(clientOptions...)
@@ -135,7 +135,7 @@ func NewClient(ctx context.Context, cfg *latest.ModelConfig, env environment.Pro
135135
client := openai.NewClient(
136136
option.WithAPIKey(authToken),
137137
option.WithBaseURL(baseURL),
138-
option.WithHTTPClient(httpclient.NewHTTPClient(httpOptions...)),
138+
option.WithHTTPClient(httpclient.NewHTTPClient(ctx, httpOptions...)),
139139
option.WithMiddleware(oaistream.ErrorBodyMiddleware()),
140140
)
141141

pkg/remote/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
// Pull pulls an artifact from a registry and stores it in the content store
1414
func Pull(ctx context.Context, registryRef string, force bool, opts ...crane.Option) (string, error) {
15-
opts = append(opts, crane.WithContext(ctx), crane.WithTransport(newTransport(ctx)))
15+
opts = append(opts, crane.WithContext(ctx), crane.WithTransport(NewTransport(ctx)))
1616

1717
ref, err := name.ParseReference(registryRef)
1818
if err != nil {

pkg/remote/push.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func Push(ctx context.Context, reference string) error {
4646
return fmt.Errorf("parsing registry reference %s: %w", reference, err)
4747
}
4848

49-
if err := crane.Push(img, ref.String(), crane.WithContext(ctx), crane.WithTransport(newTransport(ctx))); err != nil {
49+
if err := crane.Push(img, ref.String(), crane.WithContext(ctx), crane.WithTransport(NewTransport(ctx))); err != nil {
5050
return fmt.Errorf("pushing image to registry %s: %w", reference, err)
5151
}
5252

0 commit comments

Comments
 (0)