openai/openai-go

Public

mirrored from https://github.com/openai/openai-goAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

option/requestoption.go

342lines · modecode

1// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
3package option
4
5import (
6 "bytes"
7 "fmt"
8 "io"
9 "net/http"
10 "net/url"
11 "strings"
12 "sync"
13 "time"
14
15 "github.com/openai/openai-go/v3/auth"
16 "github.com/openai/openai-go/v3/internal/requestconfig"
17 "github.com/tidwall/sjson"
18)
19
20// RequestOption is an option for the requests made by the openai API Client
21// which can be supplied to clients, services, and methods. You can read more about this functional
22// options pattern in our [README].
23//
24// [README]: https://pkg.go.dev/github.com/openai/openai-go#readme-requestoptions
25type RequestOption = requestconfig.RequestOption
26
27// WithBaseURL returns a RequestOption that sets the BaseURL for the client.
28//
29// For security reasons, ensure that the base URL is trusted.
30func WithBaseURL(base string) RequestOption {
31 u, err := url.Parse(base)
32 if err == nil && u.Path != "" && !strings.HasSuffix(u.Path, "/") {
33 u.Path += "/"
34 }
35
36 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
37 if err != nil {
38 return fmt.Errorf("requestoption: WithBaseURL failed to parse url %s", err)
39 }
40
41 r.BaseURL = u
42 return nil
43 })
44}
45
46// HTTPClient is primarily used to describe an [*http.Client], but also
47// supports custom implementations.
48//
49// For bespoke implementations, prefer using an [*http.Client] with a
50// custom transport. See [http.RoundTripper] for further information.
51type HTTPClient interface {
52 Do(*http.Request) (*http.Response, error)
53}
54
55// WithHTTPClient returns a RequestOption that changes the underlying http client used to make this
56// request, which by default is [http.DefaultClient].
57//
58// For custom uses cases, it is recommended to provide an [*http.Client] with a custom
59// [http.RoundTripper] as its transport, rather than directly implementing [HTTPClient].
60func WithHTTPClient(client HTTPClient) RequestOption {
61 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
62 if client == nil {
63 return fmt.Errorf("requestoption: custom http client cannot be nil")
64 }
65
66 if c, ok := client.(*http.Client); ok {
67 // Prefer the native client if possible.
68 r.HTTPClient = c
69 r.CustomHTTPDoer = nil
70 } else {
71 r.CustomHTTPDoer = client
72 }
73
74 return nil
75 })
76}
77
78// MiddlewareNext is a function which is called by a middleware to pass an HTTP request
79// to the next stage in the middleware chain.
80type MiddlewareNext = func(*http.Request) (*http.Response, error)
81
82// Middleware is a function which intercepts HTTP requests, processing or modifying
83// them, and then passing the request to the next middleware or handler
84// in the chain by calling the provided MiddlewareNext function.
85type Middleware = func(*http.Request, MiddlewareNext) (*http.Response, error)
86
87// WithMiddleware returns a RequestOption that applies the given middleware
88// to the requests made. Each middleware will execute in the order they were given.
89func WithMiddleware(middlewares ...Middleware) RequestOption {
90 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
91 r.Middlewares = append(r.Middlewares, middlewares...)
92 return nil
93 })
94}
95
96// WithMaxRetries returns a RequestOption that sets the maximum number of retries that the client
97// attempts to make. When given 0, the client only makes one request. By
98// default, the client retries two times.
99//
100// WithMaxRetries panics when retries is negative.
101func WithMaxRetries(retries int) RequestOption {
102 if retries < 0 {
103 panic("option: cannot have fewer than 0 retries")
104 }
105 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
106 r.MaxRetries = retries
107 return nil
108 })
109}
110
111// WithHeader returns a RequestOption that sets the header value to the associated key. It overwrites
112// any value if there was one already present.
113func WithHeader(key, value string) RequestOption {
114 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
115 r.SetHeader(key, value)
116 return nil
117 })
118}
119
120// WithHeaderAdd returns a RequestOption that adds the header value to the associated key. It appends
121// onto any existing values.
122func WithHeaderAdd(key, value string) RequestOption {
123 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
124 r.AddHeader(key, value)
125 return nil
126 })
127}
128
129// WithHeaderDel returns a RequestOption that deletes the header value(s) associated with the given key.
130func WithHeaderDel(key string) RequestOption {
131 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
132 r.DelHeader(key)
133 return nil
134 })
135}
136
137// WithQuery returns a RequestOption that sets the query value to the associated key. It overwrites
138// any value if there was one already present.
139func WithQuery(key, value string) RequestOption {
140 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
141 query := r.Request.URL.Query()
142 query.Set(key, value)
143 r.Request.URL.RawQuery = query.Encode()
144 return nil
145 })
146}
147
148// WithQueryAdd returns a RequestOption that adds the query value to the associated key. It appends
149// onto any existing values.
150func WithQueryAdd(key, value string) RequestOption {
151 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
152 query := r.Request.URL.Query()
153 query.Add(key, value)
154 r.Request.URL.RawQuery = query.Encode()
155 return nil
156 })
157}
158
159// WithQueryDel returns a RequestOption that deletes the query value(s) associated with the key.
160func WithQueryDel(key string) RequestOption {
161 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
162 query := r.Request.URL.Query()
163 query.Del(key)
164 r.Request.URL.RawQuery = query.Encode()
165 return nil
166 })
167}
168
169// WithJSONSet returns a RequestOption that sets the body's JSON value associated with the key.
170// The key accepts a string as defined by the [sjson format].
171//
172// [sjson format]: https://github.com/tidwall/sjson
173func WithJSONSet(key string, value any) RequestOption {
174 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) (err error) {
175 var b []byte
176
177 if r.Body == nil {
178 b, err = sjson.SetBytes(nil, key, value)
179 if err != nil {
180 return err
181 }
182 } else if buffer, ok := r.Body.(*bytes.Buffer); ok {
183 b = buffer.Bytes()
184 b, err = sjson.SetBytes(b, key, value)
185 if err != nil {
186 return err
187 }
188 } else {
189 return fmt.Errorf("cannot use WithJSONSet on a body that is not serialized as *bytes.Buffer")
190 }
191
192 r.Body = bytes.NewBuffer(b)
193 return nil
194 })
195}
196
197// WithJSONDel returns a RequestOption that deletes the body's JSON value associated with the key.
198// The key accepts a string as defined by the [sjson format].
199//
200// [sjson format]: https://github.com/tidwall/sjson
201func WithJSONDel(key string) RequestOption {
202 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) (err error) {
203 if buffer, ok := r.Body.(*bytes.Buffer); ok {
204 b := buffer.Bytes()
205 b, err = sjson.DeleteBytes(b, key)
206 if err != nil {
207 return err
208 }
209 r.Body = bytes.NewBuffer(b)
210 return nil
211 }
212
213 return fmt.Errorf("cannot use WithJSONDel on a body that is not serialized as *bytes.Buffer")
214 })
215}
216
217// WithResponseBodyInto returns a RequestOption that overwrites the deserialization target with
218// the given destination. If provided, we don't deserialize into the default struct.
219func WithResponseBodyInto(dst any) RequestOption {
220 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
221 r.ResponseBodyInto = dst
222 return nil
223 })
224}
225
226// WithResponseInto returns a RequestOption that copies the [*http.Response] into the given address.
227func WithResponseInto(dst **http.Response) RequestOption {
228 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
229 r.ResponseInto = dst
230 return nil
231 })
232}
233
234// WithRequestBody returns a RequestOption that provides a custom serialized body with the given
235// content type.
236//
237// body accepts an io.Reader or raw []bytes.
238func WithRequestBody(contentType string, body any) RequestOption {
239 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
240 if reader, ok := body.(io.Reader); ok {
241 r.Body = reader
242 return r.Apply(WithHeader("Content-Type", contentType))
243 }
244
245 if b, ok := body.([]byte); ok {
246 r.Body = bytes.NewBuffer(b)
247 return r.Apply(WithHeader("Content-Type", contentType))
248 }
249
250 return fmt.Errorf("body must be a byte slice or implement io.Reader")
251 })
252}
253
254// WithRequestTimeout returns a RequestOption that sets the timeout for
255// each request attempt. This should be smaller than the timeout defined in
256// the context, which spans all retries.
257func WithRequestTimeout(dur time.Duration) RequestOption {
258 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
259 r.RequestTimeout = dur
260 return nil
261 })
262}
263
264// WithEnvironmentProduction returns a RequestOption that sets the current
265// environment to be the "production" environment. An environment specifies which base URL
266// to use by default.
267func WithEnvironmentProduction() RequestOption {
268 return requestconfig.WithDefaultBaseURL("https://api.openai.com/v1/")
269}
270
271// WithAPIKey returns a RequestOption that sets the client setting "api_key".
272func WithAPIKey(value string) RequestOption {
273 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
274 r.SetAPIKey(value)
275 return nil
276 })
277}
278
279// WithAdminAPIKey returns a RequestOption that sets the client setting "admin_api_key".
280func WithAdminAPIKey(value string) RequestOption {
281 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
282 r.SetAdminAPIKey(value)
283 return nil
284 })
285}
286
287// WithOrganization returns a RequestOption that sets the client setting "organization".
288func WithOrganization(value string) RequestOption {
289 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
290 r.Organization = value
291 return r.Apply(WithHeader("OpenAI-Organization", value))
292 })
293}
294
295// WithProject returns a RequestOption that sets the client setting "project".
296func WithProject(value string) RequestOption {
297 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
298 r.Project = value
299 return r.Apply(WithHeader("OpenAI-Project", value))
300 })
301}
302
303// WithWebhookSecret returns a RequestOption that sets the client setting "webhook_secret".
304func WithWebhookSecret(value string) requestconfig.PreRequestOptionFunc {
305 return requestconfig.PreRequestOptionFunc(func(r *requestconfig.RequestConfig) error {
306 r.WebhookSecret = value
307 return nil
308 })
309}
310
311// WithWorkloadIdentity returns a RequestOption that configures workload identity authentication.
312// This enables the client to authenticate using short-lived tokens from cloud providers
313// (Kubernetes, Azure, GCP) instead of long-lived API keys.
314func WithWorkloadIdentity(config auth.WorkloadIdentity) RequestOption {
315 var wia *auth.WorkloadIdentityAuth
316 var initOnce sync.Once
317 var initErr error
318
319 return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
320 r.SetAPIKey("")
321
322 r.Middlewares = append(r.Middlewares, func(req *http.Request, next func(*http.Request) (*http.Response, error)) (*http.Response, error) {
323 initOnce.Do(func() {
324 wia, initErr = auth.NewWorkloadIdentityAuth(config)
325 })
326
327 if initErr != nil {
328 return nil, initErr
329 }
330
331 var httpDoer auth.HTTPDoer
332 if r.CustomHTTPDoer != nil {
333 httpDoer = r.CustomHTTPDoer
334 } else {
335 httpDoer = r.HTTPClient
336 }
337
338 return auth.WorkloadIdentityMiddleware(wia, httpDoer, req, next)
339 })
340 return nil
341 })
342}
343