Skip to content

Commit 6eb5d85

Browse files
committed
Allow users to provide custom HTTP configuration and Google Credentials to go-genai client
1 parent 9331c82 commit 6eb5d85

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

client.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,18 @@ func NewClient(ctx context.Context, cc *ClientConfig) (*Client, error) {
261261
}
262262
cc.HTTPClient = client
263263
} else {
264-
cc.HTTPClient = &http.Client{}
264+
// If credentials are provided for Gemini API, create an authenticated HTTP client
265+
if cc.Credentials != nil {
266+
client, err := httptransport.NewClient(&httptransport.Options{
267+
Credentials: cc.Credentials,
268+
})
269+
if err != nil {
270+
return nil, fmt.Errorf("failed to create HTTP client: %w", err)
271+
}
272+
cc.HTTPClient = client
273+
} else {
274+
cc.HTTPClient = &http.Client{}
275+
}
265276
}
266277
}
267278

client_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,82 @@ func TestNewClient(t *testing.T) {
433433

434434
}
435435

436+
func TestCustomCredentialsWithGeminiAPI(t *testing.T) {
437+
// This test verifies that custom credentials are properly used when creating a client
438+
// with the Gemini API backend.
439+
ctx := context.Background()
440+
441+
// Create mock credentials
442+
mockCreds := &auth.Credentials{}
443+
444+
// Test case: Gemini API with custom credentials
445+
t.Run("GeminiAPI with custom credentials", func(t *testing.T) {
446+
client, err := NewClient(ctx, &ClientConfig{
447+
Backend: BackendGeminiAPI,
448+
APIKey: "test-api-key",
449+
Credentials: mockCreds,
450+
})
451+
if err != nil {
452+
t.Fatalf("Expected no error, got %v", err)
453+
}
454+
455+
// Verify the credentials were correctly passed to the client config
456+
if client.clientConfig.Credentials != mockCreds {
457+
t.Errorf("Credentials were not properly set in client config")
458+
}
459+
460+
// Verify that HTTPClient is not nil (it should have been created)
461+
if client.clientConfig.HTTPClient == nil {
462+
t.Errorf("Expected HTTPClient to be created, got nil")
463+
}
464+
})
465+
466+
// Test case: Custom HTTP options with Gemini API
467+
t.Run("GeminiAPI with custom HTTP options", func(t *testing.T) {
468+
customOptions := HTTPOptions{
469+
APIVersion: "custom-version",
470+
BaseURL: "https://custom-url.example.com/",
471+
}
472+
473+
client, err := NewClient(ctx, &ClientConfig{
474+
Backend: BackendGeminiAPI,
475+
APIKey: "test-api-key",
476+
HTTPOptions: customOptions,
477+
})
478+
if err != nil {
479+
t.Fatalf("Expected no error, got %v", err)
480+
}
481+
482+
// Verify HTTP options were correctly passed to the client config
483+
if client.clientConfig.HTTPOptions.APIVersion != customOptions.APIVersion {
484+
t.Errorf("Expected APIVersion %q, got %q", customOptions.APIVersion, client.clientConfig.HTTPOptions.APIVersion)
485+
}
486+
if client.clientConfig.HTTPOptions.BaseURL != customOptions.BaseURL {
487+
t.Errorf("Expected BaseURL %q, got %q", customOptions.BaseURL, client.clientConfig.HTTPOptions.BaseURL)
488+
}
489+
})
490+
491+
// Test case: Gemini API with custom credentials and HTTP client
492+
t.Run("GeminiAPI with custom credentials and HTTP client", func(t *testing.T) {
493+
customHTTPClient := &http.Client{Timeout: 10 * time.Second}
494+
495+
client, err := NewClient(ctx, &ClientConfig{
496+
Backend: BackendGeminiAPI,
497+
APIKey: "test-api-key",
498+
Credentials: mockCreds,
499+
HTTPClient: customHTTPClient,
500+
})
501+
if err != nil {
502+
t.Fatalf("Expected no error, got %v", err)
503+
}
504+
505+
// Verify custom HTTP client was used
506+
if client.clientConfig.HTTPClient != customHTTPClient {
507+
t.Errorf("Expected custom HTTP client to be used")
508+
}
509+
})
510+
}
511+
436512
func TestClientConfigHTTPOptions(t *testing.T) {
437513
tests := []struct {
438514
name string

example_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
"io"
2222
"log"
2323
"net/http"
24+
"time"
2425

26+
"cloud.google.com/go/auth"
2527
"google.golang.org/genai"
2628
)
2729

@@ -61,6 +63,47 @@ func ExampleNewClient_geminiapi() {
6163
fmt.Println(client.ClientConfig().APIKey)
6264
}
6365

66+
// This example shows how to create a new client for Gemini API with custom credentials and HTTP configuration.
67+
func ExampleNewClient_geminiapi_withCustomCredentials() {
68+
ctx := context.Background()
69+
70+
// In a real application, you would create credentials from a service account
71+
// For example, using auth.DetectDefault() or other credential methods
72+
// Here we just demonstrate with a mock credentials object
73+
creds := &auth.Credentials{}
74+
75+
// Create a custom HTTP client with specific timeouts
76+
customHTTPClient := &http.Client{
77+
Timeout: 30 * time.Second,
78+
}
79+
80+
// Create client with custom credentials and HTTP configuration
81+
client, err := genai.NewClient(ctx, &genai.ClientConfig{
82+
APIKey: apiKey,
83+
Backend: genai.BackendGeminiAPI,
84+
Credentials: creds,
85+
HTTPClient: customHTTPClient,
86+
HTTPOptions: genai.HTTPOptions{
87+
APIVersion: "v1beta", // Specify API version if needed
88+
},
89+
})
90+
if err != nil {
91+
log.Fatalf("failed to create client: %v", err)
92+
}
93+
94+
// The client now uses the custom credentials and HTTP configuration
95+
// for all API calls
96+
result, err := client.Models.GenerateContent(ctx,
97+
"gemini-2.0-flash",
98+
genai.Text("Tell me about cloud credentials?"),
99+
nil,
100+
)
101+
if err != nil {
102+
log.Fatal(err)
103+
}
104+
debugPrint(result)
105+
}
106+
64107
// This example shows how to call the GenerateContent method with a simple text to Vertex AI.
65108
func ExampleModels_GenerateContent_text_vertexai() {
66109
ctx := context.Background()

0 commit comments

Comments
 (0)