-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclient.go
More file actions
132 lines (113 loc) · 3.55 KB
/
Copy pathclient.go
File metadata and controls
132 lines (113 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2025 SIXT SE
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tensorlake
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
// Client is a Tensorlake API client.
type Client struct {
httpClient *http.Client
baseURL string
apiKey string
sandboxAPIBaseURL string
sandboxProxyBaseURL string
}
// Option defines a configuration option for the Client.
type Option func(*Client)
// WithBaseURL sets the base URL to use for the client.
func WithBaseURL(url string) Option {
return func(c *Client) {
c.baseURL = url
}
}
// WithAPIKey sets the API key to use for the client.
func WithAPIKey(key string) Option {
return func(c *Client) {
c.apiKey = key
}
}
// WithSandboxAPIBaseURL sets the base URL for sandbox management API calls.
// Default: https://api.tensorlake.ai/sandboxes
//
// Example: WithSandboxAPIBaseURL("https://api-tensorlake.orange.sixt.com/sandboxes")
func WithSandboxAPIBaseURL(url string) Option {
return func(c *Client) {
c.sandboxAPIBaseURL = url
}
}
// WithSandboxProxyBaseURL sets the base URL template for sandbox file proxy calls.
// The sandbox ID is prepended as a subdomain. The value should include the scheme
// and domain but NOT the sandbox ID subdomain.
//
// Default: https://sandbox.tensorlake.ai
//
// For a sandbox with ID "abc123", the file API URL becomes:
//
// https://abc123.sandbox.tensorlake.ai/api/v1/files
//
// Example: WithSandboxProxyBaseURL("https://sandbox-tensorlake.orange.sixt.com")
// would produce: https://abc123.sandbox-tensorlake.orange.sixt.com/api/v1/files
func WithSandboxProxyBaseURL(url string) Option {
return func(c *Client) {
c.sandboxProxyBaseURL = url
}
}
// WithHTTPClient sets the HTTP client to use for the client.
func WithHTTPClient(client *http.Client) Option {
return func(c *Client) {
c.httpClient = client
}
}
// NewClient creates a new Tensorlake API client.
func NewClient(opts ...Option) *Client {
client := &Client{
httpClient: http.DefaultClient,
baseURL: EndpointEU,
apiKey: os.Getenv("TENSORLAKE_API_KEY"),
}
for _, opt := range opts {
opt(client)
}
return client
}
func do[T any](c *Client, req *http.Request, successHandler func(io.Reader) (T, error)) (T, error) {
var zero T
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
resp, err := c.httpClient.Do(req)
if err != nil {
return zero, fmt.Errorf("failed to execute request: %w", err)
}
defer resp.Body.Close()
switch {
case resp.StatusCode >= 200 && resp.StatusCode < 300:
if successHandler != nil {
return successHandler(resp.Body)
}
return zero, nil
case resp.StatusCode >= 400:
var errRes ErrorResponse
if err := json.NewDecoder(resp.Body).Decode(&errRes); err != nil {
return zero, fmt.Errorf("failed to decode error response (%d): %w", resp.StatusCode, err)
}
return zero, &errRes
default:
bodyBytes, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) // Limit to 1MB
return zero, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(bodyBytes))
}
}