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