async_openai/
request_options.rs1use reqwest::header::HeaderMap;
2use serde::Serialize;
3use url::Url;
4
5use crate::{config::OPENAI_API_BASE, error::OpenAIError};
6
7#[derive(Clone, Debug, Default)]
8pub struct RequestOptions {
9 query: Option<Vec<(String, String)>>,
10 headers: Option<HeaderMap>,
11 path: Option<String>,
12}
13
14impl RequestOptions {
15 pub(crate) fn new() -> Self {
16 Self {
17 query: None,
18 headers: None,
19 path: None,
20 }
21 }
22
23 pub(crate) fn with_path(&mut self, path: &str) -> Result<(), OpenAIError> {
24 if path.is_empty() {
25 return Err(OpenAIError::InvalidArgument(
26 "Path cannot be empty".to_string(),
27 ));
28 }
29 self.path = Some(path.to_string());
30 Ok(())
31 }
32
33 pub(crate) fn with_headers(&mut self, headers: HeaderMap) {
34 if let Some(existing_headers) = &mut self.headers {
36 existing_headers.extend(headers);
37 } else {
38 self.headers = Some(headers);
39 }
40 }
41
42 pub(crate) fn with_header<K, V>(&mut self, key: K, value: V) -> Result<(), OpenAIError>
43 where
44 K: reqwest::header::IntoHeaderName,
45 V: TryInto<reqwest::header::HeaderValue>,
46 V::Error: Into<reqwest::header::InvalidHeaderValue>,
47 {
48 let value = value.try_into().map_err(|e| {
49 OpenAIError::InvalidArgument(format!("Invalid header value: {}", e.into()))
50 })?;
51 if let Some(headers) = &mut self.headers {
52 headers.insert(key, value);
53 } else {
54 let mut headers = HeaderMap::new();
55 headers.insert(key, value);
56 self.headers = Some(headers);
57 }
58 Ok(())
59 }
60
61 pub(crate) fn with_query<Q: Serialize + ?Sized>(
62 &mut self,
63 query: &Q,
64 ) -> Result<(), OpenAIError> {
65 let mut url = Url::parse(OPENAI_API_BASE)
69 .map_err(|e| OpenAIError::InvalidArgument(format!("Failed to create URL: {}", e)))?;
70
71 {
72 let mut pairs = url.query_pairs_mut();
73 let serializer = serde_urlencoded::Serializer::new(&mut pairs);
74
75 query
76 .serialize(serializer)
77 .map_err(|e| OpenAIError::InvalidArgument(format!("Invalid query: {}", e)))?;
78 }
79
80 let query = self.query.get_or_insert_with(Vec::new);
82 for (key, value) in url.query_pairs() {
83 query.push((key.to_string(), value.to_string()));
84 }
85
86 Ok(())
87 }
88
89 pub(crate) fn query(&self) -> &[(String, String)] {
90 self.query.as_deref().unwrap_or(&[])
91 }
92
93 pub(crate) fn headers(&self) -> Option<&HeaderMap> {
94 self.headers.as_ref()
95 }
96
97 pub(crate) fn path(&self) -> Option<&String> {
98 self.path.as_ref()
99 }
100}