requestoption.go

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