use std::fmt::Debug;
use std::sync::Arc;
use salvo_core::http::header::{self, HeaderName, HeaderValue};
use salvo_core::{Depot, Request};
use super::inner::BoolInner;
#[derive(Clone, Default, Debug)]
#[must_use]
pub struct AllowCredentials(BoolInner);
impl AllowCredentials {
pub fn yes() -> Self {
Self(BoolInner::Yes)
}
pub fn dynamic<P>(p: P) -> Self
where
P: Fn(Option<&HeaderValue>, &Request, &Depot) -> bool + Send + Sync + 'static,
{
Self(BoolInner::Dynamic(Arc::new(p)))
}
pub fn dynamic_async<P, Fut>(p: P) -> Self
where
P: Fn(Option<&HeaderValue>, &Request, &Depot) -> Fut + Send + Sync + 'static,
Fut: Future<Output = bool> + Send + 'static,
{
Self(BoolInner::DynamicAsync(Arc::new(
move |header, req, depot| Box::pin(p(header, req, depot)),
)))
}
pub(super) fn is_true(&self) -> bool {
matches!(&self.0, BoolInner::Yes)
}
pub(super) async fn to_header(
&self,
origin: Option<&HeaderValue>,
req: &Request,
depot: &Depot,
) -> Option<(HeaderName, HeaderValue)> {
self.0.resolve_async(origin, req, depot).await.then_some((
header::ACCESS_CONTROL_ALLOW_CREDENTIALS,
HeaderValue::from_static("true"),
))
}
}
impl From<bool> for AllowCredentials {
fn from(v: bool) -> Self {
match v {
true => Self(BoolInner::Yes),
false => Self(BoolInner::No),
}
}
}
#[cfg(test)]
mod tests {
use super::AllowCredentials;
#[test]
fn test_from_bool() {
let creds: AllowCredentials = true.into();
assert!(creds.is_true());
let creds: AllowCredentials = false.into();
assert!(!creds.is_true());
}
}