1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::{fmt, sync::Arc};
use http::{
header::{self, HeaderName, HeaderValue},
request::Parts as RequestParts,
};
#[derive(Clone, Default)]
#[must_use]
pub struct AllowCredentials(AllowCredentialsInner);
impl AllowCredentials {
pub fn yes() -> Self {
Self(AllowCredentialsInner::Yes)
}
pub fn predicate<F>(f: F) -> Self
where
F: Fn(&HeaderValue, &RequestParts) -> bool + Send + Sync + 'static,
{
Self(AllowCredentialsInner::Predicate(Arc::new(f)))
}
pub(super) fn is_true(&self) -> bool {
matches!(&self.0, AllowCredentialsInner::Yes)
}
pub(super) fn to_header(
&self,
origin: Option<&HeaderValue>,
parts: &RequestParts,
) -> Option<(HeaderName, HeaderValue)> {
#[allow(clippy::declare_interior_mutable_const)]
const TRUE: HeaderValue = HeaderValue::from_static("true");
let allow_creds = match &self.0 {
AllowCredentialsInner::Yes => true,
AllowCredentialsInner::No => false,
AllowCredentialsInner::Predicate(c) => c(origin?, parts),
};
allow_creds.then(|| (header::ACCESS_CONTROL_ALLOW_CREDENTIALS, TRUE))
}
}
impl From<bool> for AllowCredentials {
fn from(v: bool) -> Self {
match v {
true => Self(AllowCredentialsInner::Yes),
false => Self(AllowCredentialsInner::No),
}
}
}
impl fmt::Debug for AllowCredentials {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
AllowCredentialsInner::Yes => f.debug_tuple("Yes").finish(),
AllowCredentialsInner::No => f.debug_tuple("No").finish(),
AllowCredentialsInner::Predicate(_) => f.debug_tuple("Predicate").finish(),
}
}
}
#[derive(Clone)]
enum AllowCredentialsInner {
Yes,
No,
Predicate(
Arc<dyn for<'a> Fn(&'a HeaderValue, &'a RequestParts) -> bool + Send + Sync + 'static>,
),
}
impl Default for AllowCredentialsInner {
fn default() -> Self {
Self::No
}
}