use std::sync::LazyLock;
use std::time::Duration;
use async_trait::async_trait;
use reqwest::{Client, Response};
use crate::tls::install_default_crypto_provider;
use crate::{CredentialError, CredentialResult};
const USER_AGENT: &str = concat!("spiral-sdk/", env!("CARGO_PKG_VERSION"));
static SHARED_CLIENT: LazyLock<Client> = LazyLock::new(|| {
install_default_crypto_provider();
#[expect(
clippy::disallowed_methods,
reason = "credential requests do not use the server HTTP client policy"
)]
let builder = Client::builder();
builder
.user_agent(USER_AGENT)
.connect_timeout(Duration::from_secs(10))
.timeout(Duration::from_secs(60))
.build()
.expect("valid credential HTTP client")
});
pub(crate) fn shared_client() -> Client {
SHARED_CLIENT.clone()
}
#[async_trait]
pub(crate) trait Accepted: Sized {
async fn accepted(self) -> CredentialResult<Self>;
}
#[async_trait]
impl Accepted for Response {
async fn accepted(self) -> CredentialResult<Self> {
let status = self.status();
if status.is_success() {
return Ok(self);
}
let url = self.url().clone();
let body = self.text().await?;
Err(CredentialError::Rejected { url, status, body })
}
}