From 606deed8c1e616b3a35c46f51e59eb94e77ddc5f Mon Sep 17 00:00:00 2001 From: Sebastien Tardif Date: Sun, 16 Aug 2026 15:45:09 -0700 Subject: [PATCH] fix(places): apply Timeout when HTTPClient has none NewClient only set Timeout when HTTPClient was nil. Callers that passed &http.Client{} (or any client with Timeout 0) ignored Options.Timeout and hung forever on a stalled Places request. Clone the provided client and apply Timeout (default 10s) when it is still zero. Explicit non-zero timeouts are left alone. Red: go test ./internal/places -run TestNewClientAppliesTimeoutToProvidedClient timeout=0s want 2s Green: same command ok Signed-off-by: Sebastien Tardif --- internal/places/client.go | 12 ++++++++---- internal/places/client_options_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/internal/places/client.go b/internal/places/client.go index aaafb58..5513268 100644 --- a/internal/places/client.go +++ b/internal/places/client.go @@ -51,13 +51,17 @@ func NewClient(opts Options) *Client { directionsBaseURL = defaultDirectionsBaseURL } + timeout := opts.Timeout + if timeout == 0 { + timeout = 10 * time.Second + } client := opts.HTTPClient if client == nil { - timeout := opts.Timeout - if timeout == 0 { - timeout = 10 * time.Second - } client = &http.Client{Timeout: timeout} + } else if client.Timeout == 0 { + cloned := *client + cloned.Timeout = timeout + client = &cloned } return &Client{ diff --git a/internal/places/client_options_test.go b/internal/places/client_options_test.go index 8fce312..19889ec 100644 --- a/internal/places/client_options_test.go +++ b/internal/places/client_options_test.go @@ -3,7 +3,9 @@ package places import ( "context" "errors" + "net/http" "testing" + "time" ) func TestMissingAPIKey(t *testing.T) { @@ -92,6 +94,30 @@ func TestValidationErrors(t *testing.T) { } } +func TestNewClientAppliesTimeoutToProvidedClient(t *testing.T) { + provided := &http.Client{} + client := NewClient(Options{ + APIKey: "test-key", + HTTPClient: provided, + Timeout: 2 * time.Second, + }) + if client.httpClient.Timeout != 2*time.Second { + t.Fatalf("timeout=%s want 2s", client.httpClient.Timeout) + } + if provided.Timeout != 0 { + t.Fatalf("mutated caller client timeout=%s", provided.Timeout) + } + explicit := &http.Client{Timeout: 7 * time.Second} + kept := NewClient(Options{ + APIKey: "test-key", + HTTPClient: explicit, + Timeout: 2 * time.Second, + }) + if kept.httpClient.Timeout != 7*time.Second { + t.Fatalf("explicit timeout=%s want 7s", kept.httpClient.Timeout) + } +} + func TestNewClientDefaults(t *testing.T) { client := NewClient(Options{APIKey: "test-key"}) if client.baseURL != DefaultBaseURL {