rama_http/layer/csrf/
layer.rs1use std::fmt::{self, Debug, Formatter};
2use std::sync::Arc;
3
4use rama_core::Layer;
5
6use super::origin::{Origins, parse_trusted_origin};
7use super::service::Csrf;
8use super::{BypassFn, ConfigError, DebugFn, DefaultResponseForProtectionError};
9use crate::Method;
10use rama_net::uri::Uri;
11
12#[derive(Clone)]
16#[must_use]
17pub struct CsrfLayer<T = DefaultResponseForProtectionError> {
18 insecure_bypass: Option<Arc<BypassFn>>,
19 rejection_response: T,
20 trusted_origins: Origins,
21}
22
23impl Default for CsrfLayer {
24 fn default() -> Self {
25 Self {
26 insecure_bypass: None,
27 rejection_response: DefaultResponseForProtectionError,
28 trusted_origins: Origins::default(),
29 }
30 }
31}
32
33impl<T> Debug for CsrfLayer<T> {
34 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
35 f.debug_struct("CsrfLayer")
36 .field(
37 "insecure_bypass",
38 &self.insecure_bypass.as_ref().map(|_| DebugFn),
39 )
40 .field("trusted_origins", &self.trusted_origins)
41 .field("rejection_response", &DebugFn)
42 .finish()
43 }
44}
45
46impl CsrfLayer {
47 pub fn new() -> Self {
50 Self::default()
51 }
52}
53
54impl<T> CsrfLayer<T> {
55 pub fn add_trusted_origin<S: AsRef<str>>(mut self, origin: S) -> Result<Self, ConfigError> {
63 let origin = parse_trusted_origin(origin.as_ref())?;
64 self.trusted_origins.insert(origin);
65 Ok(self)
66 }
67
68 pub fn with_insecure_bypass<F>(mut self, predicate: F) -> Self
74 where
75 F: Fn(&Method, &Uri) -> bool + Send + Sync + 'static,
76 {
77 self.insecure_bypass = Some(Arc::new(predicate));
78 self
79 }
80
81 pub fn with_rejection_response<R>(self, rejection_response: R) -> CsrfLayer<R>
90 where
91 R: Clone,
92 {
93 CsrfLayer {
94 insecure_bypass: self.insecure_bypass,
95 trusted_origins: self.trusted_origins,
96 rejection_response,
97 }
98 }
99}
100
101impl<S, T> Layer<S> for CsrfLayer<T>
102where
103 T: Clone,
104{
105 type Service = Csrf<S, T>;
106
107 fn layer(&self, inner: S) -> Self::Service {
108 Csrf::new(
109 inner,
110 self.insecure_bypass.clone(),
111 self.rejection_response.clone(),
112 self.trusted_origins.clone(),
113 )
114 }
115
116 fn into_layer(self, inner: S) -> Self::Service {
117 Csrf::new(
118 inner,
119 self.insecure_bypass,
120 self.rejection_response,
121 self.trusted_origins,
122 )
123 }
124}