use std::sync::{Arc, RwLock};
pub trait Auth: Send + Sync {
fn authorization_header(&self) -> Option<String>;
}
#[derive(Clone)]
pub struct BearerAuth {
provider: Arc<dyn Fn() -> String + Send + Sync>,
}
impl std::fmt::Debug for BearerAuth {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BearerAuth").finish_non_exhaustive()
}
}
impl BearerAuth {
pub fn new(token: impl Into<String>) -> Self {
let token = token.into();
Self::dynamic(move || token.clone())
}
pub fn dynamic(provider: impl Fn() -> String + Send + Sync + 'static) -> Self {
Self {
provider: Arc::new(provider),
}
}
pub fn shared(token: Arc<RwLock<String>>) -> Self {
Self::dynamic(move || token.read().expect("token lock poisoned").clone())
}
}
impl Auth for BearerAuth {
fn authorization_header(&self) -> Option<String> {
let mut token = (self.provider)().trim().to_string();
if token.is_empty() {
return None;
}
if let Some(rest) = token.strip_prefix("Bearer ") {
token = rest.to_string();
}
Some(format!("Bearer {token}"))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct NoAuth;
impl Auth for NoAuth {
fn authorization_header(&self) -> Option<String> {
None
}
}