From 1d0e79f37e901f69d6025bc3e6f17ace9516f3a6 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Mon, 22 Sep 2025 17:26:36 +0400 Subject: [PATCH] chore: refactor InitClient() to use ClientOptions (#19761) Refactors `InitClient` and friends to use the ClientBuilder rather than modifying a Client in place. --- cli/root.go | 70 ++++++++++++++++++++++++++++++------------------ cli/vscodessh.go | 13 ++++----- 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/cli/root.go b/cli/root.go index 09763fce44..828dc9944f 100644 --- a/cli/root.go +++ b/cli/root.go @@ -529,19 +529,29 @@ func (r *RootCmd) InitClient(inv *serpent.Invocation) (*codersdk.Client, error) } } - client := &codersdk.Client{} - err = r.configureClient(inv.Context(), client, r.clientURL, inv) + // Configure HTTP client with transport wrappers + httpClient, err := r.createHTTPClient(inv.Context(), r.clientURL, inv) if err != nil { return nil, err } - client.SetSessionToken(r.token) + + clientOpts := []codersdk.ClientOption{ + codersdk.WithSessionToken(r.token), + codersdk.WithHTTPClient(httpClient), + } + + if r.disableDirect { + clientOpts = append(clientOpts, codersdk.WithDisableDirectConnections()) + } if r.debugHTTP { - client.PlainLogger = os.Stderr - client.SetLogBodies(true) + clientOpts = append(clientOpts, + codersdk.WithPlainLogger(os.Stderr), + codersdk.WithLogBodies(), + ) } - client.DisableDirectConnections = r.disableDirect - return client, nil + + return codersdk.New(r.clientURL, clientOpts...), nil } // TryInitClient is similar to InitClient but doesn't error when credentials are missing. @@ -577,19 +587,29 @@ func (r *RootCmd) TryInitClient(inv *serpent.Invocation) (*codersdk.Client, erro // Only configure the client if we have a URL if r.clientURL != nil && r.clientURL.String() != "" { - client := &codersdk.Client{} - err = r.configureClient(inv.Context(), client, r.clientURL, inv) + // Configure HTTP client with transport wrappers + httpClient, err := r.createHTTPClient(inv.Context(), r.clientURL, inv) if err != nil { return nil, err } - client.SetSessionToken(r.token) + + clientOpts := []codersdk.ClientOption{ + codersdk.WithSessionToken(r.token), + codersdk.WithHTTPClient(httpClient), + } + + if r.disableDirect { + clientOpts = append(clientOpts, codersdk.WithDisableDirectConnections()) + } if r.debugHTTP { - client.PlainLogger = os.Stderr - client.SetLogBodies(true) + clientOpts = append(clientOpts, + codersdk.WithPlainLogger(os.Stderr), + codersdk.WithLogBodies(), + ) } - client.DisableDirectConnections = r.disableDirect - return client, nil + + return codersdk.New(r.clientURL, clientOpts...), nil } // Return a minimal client if no URL is available @@ -602,10 +622,7 @@ func (r *RootCmd) HeaderTransport(ctx context.Context, serverURL *url.URL) (*cod return headerTransport(ctx, serverURL, r.header, r.headerCommand) } -func (r *RootCmd) configureClient(ctx context.Context, client *codersdk.Client, serverURL *url.URL, inv *serpent.Invocation) error { - if client.SessionTokenProvider == nil { - client.SessionTokenProvider = codersdk.FixedSessionTokenProvider{} - } +func (r *RootCmd) createHTTPClient(ctx context.Context, serverURL *url.URL, inv *serpent.Invocation) (*http.Client, error) { transport := http.DefaultTransport transport = wrapTransportWithTelemetryHeader(transport, inv) if !r.noVersionCheck { @@ -621,23 +638,24 @@ func (r *RootCmd) configureClient(ctx context.Context, client *codersdk.Client, } headerTransport, err := r.HeaderTransport(ctx, serverURL) if err != nil { - return xerrors.Errorf("create header transport: %w", err) + return nil, xerrors.Errorf("create header transport: %w", err) } // The header transport has to come last. // codersdk checks for the header transport to get headers // to clone on the DERP client. headerTransport.Transport = transport - client.HTTPClient = &http.Client{ + return &http.Client{ Transport: headerTransport, - } - client.URL = serverURL - return nil + }, nil } func (r *RootCmd) createUnauthenticatedClient(ctx context.Context, serverURL *url.URL, inv *serpent.Invocation) (*codersdk.Client, error) { - var client codersdk.Client - err := r.configureClient(ctx, &client, serverURL, inv) - return &client, err + httpClient, err := r.createHTTPClient(ctx, serverURL, inv) + if err != nil { + return nil, err + } + client := codersdk.New(serverURL, codersdk.WithHTTPClient(httpClient)) + return client, nil } type AgentAuth struct { diff --git a/cli/vscodessh.go b/cli/vscodessh.go index bd249b0a6f..7792958a91 100644 --- a/cli/vscodessh.go +++ b/cli/vscodessh.go @@ -79,14 +79,15 @@ func (r *RootCmd) vscodeSSH() *serpent.Command { ctx, cancel := context.WithCancel(inv.Context()) defer cancel() - client := codersdk.New(serverURL) - client.SetSessionToken(string(sessionToken)) - - // This adds custom headers to the request! - err = r.configureClient(ctx, client, serverURL, inv) + // Configure HTTP client with transport wrappers + httpClient, err := r.createHTTPClient(ctx, serverURL, inv) if err != nil { - return xerrors.Errorf("set client: %w", err) + return xerrors.Errorf("create HTTP client: %w", err) } + client := codersdk.New(serverURL, + codersdk.WithSessionToken(string(sessionToken)), + codersdk.WithHTTPClient(httpClient), + ) parts := strings.Split(inv.Args[0], "--") if len(parts) < 3 {