use reqwest::header::{HeaderMap, HeaderValue};
use serde::Serialize;
use crate::logging;
use crate::models::HttpResult;
use crate::routes::CompiledRoute;
static BASE_API_URL: &str = "https://api.unkey.dev/v1";
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, Clone)]
pub(crate) struct HttpService {
url: String,
client: reqwest::Client,
headers: HeaderMap,
}
impl HttpService {
#[must_use]
#[rustfmt::skip]
pub fn new(key: &str) -> Self {
let headers = Self::generate_headers(key);
let client = reqwest::Client::new();
let url = BASE_API_URL.to_string();
Self { url, client, headers }
}
#[must_use]
#[rustfmt::skip]
pub fn with_url(key: &str, url: &str) -> Self {
let headers = Self::generate_headers(key);
let client = reqwest::Client::new();
let url = url.to_string();
Self { url, client, headers }
}
fn generate_headers(key: &str) -> HeaderMap {
let mut headers = HeaderMap::with_capacity(3);
let key = format!("Bearer {key}");
let version = env!("CARGO_PKG_VERSION");
let user_agent = format!("unkey.rs@v{version}");
let buffer: [(&'static str, Result<HeaderValue, _>); 5] = [
("Accept", HeaderValue::from_str("application/json")),
("x-user-agent", HeaderValue::from_str(&user_agent)),
("User-Agent", HeaderValue::from_str(&user_agent)),
("Unkey-SDK", HeaderValue::from_str(&user_agent)),
("Authorization", HeaderValue::from_str(&key)),
];
for (k, v) in &buffer {
match v {
Ok(h) => headers.insert(*k, h.clone()),
Err(e) => {
eprintln!("Invalid header value: {e:?}");
std::process::exit(1);
}
};
}
headers
}
pub fn set_key(&mut self, key: &str) {
let header = HeaderValue::from_str(key);
match header {
Err(e) => eprintln!("Error setting header value: {e:?}"),
Ok(h) => {
self.headers.insert("Authorization", h);
}
}
}
pub fn set_url(&mut self, url: &str) {
self.url = url.to_string();
}
pub async fn fetch<T>(&self, route: CompiledRoute, payload: Option<T>) -> HttpResult
where
T: std::fmt::Debug + Serialize,
{
let query = route.build_query();
let endpoint = route.uri.clone() + &query;
logging::info!(format!("OUTGOING: {} {endpoint}", &route.method));
let url = self.url.clone() + &endpoint;
let mut req = self
.client
.request(route.method, url)
.headers(self.headers.clone());
if let Some(p) = payload {
logging::debug!(format!("PAYLOAD : {p:?}"));
req = req.json(&p);
}
req.send().await
}
}