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
2 changes: 1 addition & 1 deletion pkg/platformclient/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (c *HTTPClient) DeleteApp(id string) error {
return err
}
req.Header.Add("Authorization", c.apiKey)
resp, err := http.DefaultClient.Do(req)
resp, err := httpClient.Do(req)
if err != nil {
return fmt.Errorf("DeleteApp (%s %s): %w", req.Method, endpoint, err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/platformclient/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (c *HTTPClient) ArchiveChannel(appID, channelID string) error {
return err
}
req.Header.Add("Authorization", c.apiKey)
resp, err := http.DefaultClient.Do(req)
resp, err := httpClient.Do(req)
if err != nil {
return fmt.Errorf("ArchiveChannel (%s %s): %w", req.Method, endpoint, err)
}
Expand Down
47 changes: 44 additions & 3 deletions pkg/platformclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import (
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
"strings"
"time"

"github.com/pkg/errors"
"github.com/replicatedhq/replicated/pkg/version"
Expand All @@ -20,6 +23,44 @@ var (
ErrForbidden = errors.New("the action is not allowed for the current user or team")
)

// httpClient is a custom HTTP client that handles .localhost domains properly.
// Go's default DNS resolver doesn't handle .localhost domains like browsers do
// (per RFC 6761), so we need custom logic to resolve them to 127.0.0.1.
// This is a singleton that's reused for all requests to avoid leaking connections.
var httpClient = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
// Check if the address is a .localhost domain
host, port, err := net.SplitHostPort(addr)
if err != nil {
// If there's no port, just use the address as host
host = addr
port = ""
}

// If the host ends with .localhost, replace it with 127.0.0.1
if strings.HasSuffix(host, ".localhost") {
if port != "" {
addr = net.JoinHostPort("127.0.0.1", port)
} else {
addr = "127.0.0.1"
}
}

dialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
return dialer.DialContext(ctx, network, addr)
},
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom HTTP transport loses proxy environment variable support

Medium Severity

The custom http.Transport doesn't set the Proxy field, which defaults to nil. Previously, the code used http.DefaultClient which uses http.DefaultTransport with Proxy: http.ProxyFromEnvironment. This means environment variables like HTTP_PROXY, HTTPS_PROXY, and NO_PROXY are now ignored for all requests, not just .localhost ones. Users behind corporate proxies or in environments requiring proxy configuration will have their requests fail.

Fix in Cursor Fix in Web


type APIError struct {
Method string
Endpoint string
Expand Down Expand Up @@ -83,7 +124,7 @@ func (c *HTTPClient) DoJSONWithoutUnmarshal(method string, path string, reqBody
req.Header.Set("Authorization", c.apiKey)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -133,7 +174,7 @@ func (c *HTTPClient) DoJSON(ctx context.Context, method string, path string, suc
return errors.Wrap(err, "add github actions headers")
}

resp, err := http.DefaultClient.Do(req)
resp, err := httpClient.Do(req)
if err != nil {
return err
}
Expand Down Expand Up @@ -222,7 +263,7 @@ func (c *HTTPClient) HTTPGet(path string, successStatus int) ([]byte, error) {
}

req.Header.Set("Authorization", c.apiKey)
resp, err := http.DefaultClient.Do(req)
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/platformclient/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (c *HTTPClient) UpdateRelease(appID string, sequence int64, yaml string) er
}
req.Header.Set("Authorization", c.apiKey)
req.Header.Set("Content-Type", "application/yaml")
resp, err := http.DefaultClient.Do(req)
resp, err := httpClient.Do(req)
if err != nil {
return fmt.Errorf("UpdateRelease: %w", err)
}
Expand Down
Loading