Optional auth header and with api keys #157 (#1)

* made key optional

* with api version
This commit is contained in:
Hitesh Joshi
2025-04-18 12:56:57 +05:30
committed by GitHub
parent 19458d8253
commit 67f5b49985
2 changed files with 29 additions and 24 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "openai-api-rs" name = "openai-api-rs"
version = "6.0.4" version = "6.0.3"
edition = "2021" edition = "2021"
authors = ["Dongri Jin <dongrium@gmail.com>"] authors = ["Dongri Jin <dongrium@gmail.com>"]
license = "MIT" license = "MIT"
@ -14,8 +14,6 @@ default = ["default-tls"]
rustls = ["reqwest/rustls-tls", "tokio-tungstenite/rustls-tls-webpki-roots"] rustls = ["reqwest/rustls-tls", "tokio-tungstenite/rustls-tls-webpki-roots"]
default-tls = ["reqwest/default-tls", "tokio-tungstenite/native-tls"] default-tls = ["reqwest/default-tls", "tokio-tungstenite/native-tls"]
[dependencies]
tracing = "0.1.41"
[dependencies.reqwest] [dependencies.reqwest]
version = "0.12" version = "0.12"

View File

@ -56,6 +56,7 @@ const API_URL_V1: &str = "https://api.openai.com/v1";
pub struct OpenAIClientBuilder { pub struct OpenAIClientBuilder {
api_endpoint: Option<String>, api_endpoint: Option<String>,
api_key: Option<String>, api_key: Option<String>,
api_version: Option<String>,
organization: Option<String>, organization: Option<String>,
proxy: Option<String>, proxy: Option<String>,
timeout: Option<u64>, timeout: Option<u64>,
@ -65,7 +66,8 @@ pub struct OpenAIClientBuilder {
#[derive(Debug)] #[derive(Debug)]
pub struct OpenAIClient { pub struct OpenAIClient {
api_endpoint: String, api_endpoint: String,
api_key: String, api_key: Option<String>,
api_version: Option<String>,
organization: Option<String>, organization: Option<String>,
proxy: Option<String>, proxy: Option<String>,
timeout: Option<u64>, timeout: Option<u64>,
@ -82,6 +84,11 @@ impl OpenAIClientBuilder {
self self
} }
pub fn with_api_version(mut self, api_version: impl Into<String>) -> Self {
self.api_version = Some(api_version.into());
self
}
pub fn with_endpoint(mut self, endpoint: impl Into<String>) -> Self { pub fn with_endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.api_endpoint = Some(endpoint.into()); self.api_endpoint = Some(endpoint.into());
self self
@ -112,14 +119,14 @@ impl OpenAIClientBuilder {
} }
pub fn build(self) -> Result<OpenAIClient, Box<dyn Error>> { pub fn build(self) -> Result<OpenAIClient, Box<dyn Error>> {
let api_key = self.api_key.ok_or("API key is required")?;
let api_endpoint = self.api_endpoint.unwrap_or_else(|| { let api_endpoint = self.api_endpoint.unwrap_or_else(|| {
std::env::var("OPENAI_API_BASE").unwrap_or_else(|_| API_URL_V1.to_owned()) std::env::var("OPENAI_API_BASE").unwrap_or_else(|_| API_URL_V1.to_owned())
}); });
Ok(OpenAIClient { Ok(OpenAIClient {
api_endpoint, api_endpoint,
api_key, api_version: self.api_version,
api_key: self.api_key,
organization: self.organization, organization: self.organization,
proxy: self.proxy, proxy: self.proxy,
timeout: self.timeout, timeout: self.timeout,
@ -134,7 +141,13 @@ impl OpenAIClient {
} }
async fn build_request(&self, method: Method, path: &str) -> reqwest::RequestBuilder { async fn build_request(&self, method: Method, path: &str) -> reqwest::RequestBuilder {
let url = format!("{}/{}", self.api_endpoint, path); let url = format!(
"{}/{}?api-version={}",
self.api_endpoint,
path,
self.api_version.as_deref().unwrap_or("v1")
);
let client = Client::builder(); let client = Client::builder();
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
@ -154,9 +167,14 @@ impl OpenAIClient {
let client = client.build().unwrap(); let client = client.build().unwrap();
let mut request = client let mut request = client.request(method, url);
.request(method, url)
.header("Authorization", format!("Bearer {}", self.api_key)); if self.api_key.is_some() {
request = request.header(
"Authorization",
format!("Bearer {}", self.api_key.as_ref().unwrap()),
);
}
if let Some(organization) = &self.organization { if let Some(organization) = &self.organization {
request = request.header("openai-organization", organization); request = request.header("openai-organization", organization);
@ -180,20 +198,9 @@ impl OpenAIClient {
path: &str, path: &str,
body: &impl serde::ser::Serialize, body: &impl serde::ser::Serialize,
) -> Result<T, APIError> { ) -> Result<T, APIError> {
let request_builder = self.build_request(Method::POST, path).await; let request = self.build_request(Method::POST, path).await;
let request_builder = request_builder.json(body); let request = request.json(body);
let response = request.send().await?;
// 💡 Convert to request to inspect it before sending
let client = request_builder
.try_clone()
.expect("Cannot clone request builder")
.build()
.expect("Failed to build request");
// 🔍 Debug log: URL, headers, and optionally body
tracing::debug!("🔵 URL: {}", client.url());
tracing::debug!("🟢 Headers:\n{:#?}", client.headers());
let response = request_builder.send().await?;
self.handle_response(response).await self.handle_response(response).await
} }