use crate::{
API_KEY, DEFAULT_BASE_URL,
client::OpenFIGIClient,
error::{OpenFIGIError, Result},
};
use reqwest::Client as ReqwestClient;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use url::Url;
pub struct OpenFIGIClientBuilder {
reqwest_client: Option<ReqwestClient>,
middleware_client: Option<ClientWithMiddleware>,
base_url: Option<String>,
api_key: Option<String>,
}
impl Default for OpenFIGIClientBuilder {
fn default() -> Self {
Self {
reqwest_client: None,
middleware_client: None,
base_url: None,
api_key: None,
}
}
}
impl OpenFIGIClientBuilder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn base_url(mut self, url: impl Into<String>) -> Self {
self.base_url = Some(url.into());
self
}
#[must_use]
pub fn api_key(mut self, key: impl Into<String>) -> Self {
self.api_key = Some(key.into());
self
}
#[must_use]
pub fn reqwest_client(mut self, client: ReqwestClient) -> Self {
self.reqwest_client = Some(client);
self
}
#[must_use]
pub fn middleware_client(mut self, client: ClientWithMiddleware) -> Self {
self.middleware_client = Some(client);
self
}
pub fn build(self) -> Result<OpenFIGIClient> {
let client = match (self.middleware_client, self.reqwest_client) {
(Some(middleware_client), _) => middleware_client,
(None, Some(reqwest_client)) => ClientBuilder::new(reqwest_client).build(),
(None, None) => ClientBuilder::new(ReqwestClient::default()).build(),
};
let base_url = match self.base_url {
Some(url_str) => Url::parse(&url_str).map_err(OpenFIGIError::from)?,
None => DEFAULT_BASE_URL.clone(),
};
let api_key = self.api_key.or(API_KEY.clone());
Ok(OpenFIGIClient::new_with_components(
client, base_url, api_key,
))
}
}
#[cfg(test)]
mod tests {
use super::*;
use reqwest::Client as ReqwestClient;
use reqwest_middleware::ClientBuilder;
use reqwest_retry::{RetryTransientMiddleware, policies::ExponentialBackoff};
#[test]
fn test_builder_basic() {
let client = OpenFIGIClientBuilder::new()
.build()
.expect("Client build should succeed");
assert_eq!(client.base_url().as_str(), DEFAULT_BASE_URL.as_str());
}
#[test]
fn test_builder_base_url() {
let custom_url = "https://api-custom.openfigi.com/v3/";
let client = OpenFIGIClientBuilder::new()
.base_url(custom_url)
.build()
.expect("Client build should succeed");
assert_eq!(client.base_url().as_str(), custom_url);
}
#[test]
fn test_builder_api_key() {
let client = OpenFIGIClientBuilder::new()
.api_key("test_key")
.build()
.expect("Client build should succeed");
assert!(client.has_api_key());
}
#[test]
fn test_builder_reqwest_client() {
let reqwest_client = ReqwestClient::new();
let client = OpenFIGIClientBuilder::new()
.reqwest_client(reqwest_client)
.build()
.expect("Client build should succeed");
assert_eq!(client.base_url().as_str(), DEFAULT_BASE_URL.as_str());
}
#[test]
fn test_builder_middleware_client() {
let reqwest_client = ReqwestClient::new();
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(3);
let middleware_client = ClientBuilder::new(reqwest_client)
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.build();
let client = OpenFIGIClientBuilder::new()
.middleware_client(middleware_client)
.build()
.expect("Client build should succeed");
assert_eq!(client.base_url().as_str(), DEFAULT_BASE_URL.as_str());
}
#[test]
fn test_builder_invalid_url() {
let result = OpenFIGIClientBuilder::new()
.base_url("not-a-valid-url")
.build();
assert!(result.is_err());
}
#[test]
fn test_builder_middleware_precedence() {
let reqwest_client = ReqwestClient::new();
let middleware_client = ClientBuilder::new(ReqwestClient::new()).build();
let client = OpenFIGIClientBuilder::new()
.reqwest_client(reqwest_client)
.middleware_client(middleware_client)
.build()
.expect("Client build should succeed");
assert_eq!(client.base_url().as_str(), DEFAULT_BASE_URL.as_str());
}
#[test]
fn test_builder_chaining() {
let client = OpenFIGIClientBuilder::new()
.base_url("https://api-custom.openfigi.com/v3/")
.api_key("test_key")
.reqwest_client(ReqwestClient::new())
.build()
.expect("Client build should succeed");
assert_eq!(
client.base_url().as_str(),
"https://api-custom.openfigi.com/v3/"
);
assert!(client.has_api_key());
}
}