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