Skip to main content

rama_http/layer/csrf/
response.rs

1use super::ProtectionError;
2use crate::{Response, StatusCode};
3
4/// Builds the response returned by [`Csrf`] when a request fails CSRF protection.
5///
6/// Implemented for any `Fn(ProtectionError) -> Response<B> + Clone + Send + Sync + 'static`, so a
7/// closure can be passed directly to
8/// [`CsrfLayer::with_rejection_response`](super::CsrfLayer::with_rejection_response).
9///
10/// [`Csrf`]: super::Csrf
11pub trait ResponseForProtectionError<B>: Clone + Send + Sync + 'static {
12    /// Builds the response from the rejection error.
13    fn response_for_protection_error(&self, error: ProtectionError) -> Response<B>;
14}
15
16impl<F, B> ResponseForProtectionError<B> for F
17where
18    F: Fn(ProtectionError) -> Response<B> + Clone + Send + Sync + 'static,
19{
20    fn response_for_protection_error(&self, error: ProtectionError) -> Response<B> {
21        self(error)
22    }
23}
24
25/// Default [`ResponseForProtectionError`] used by [`CsrfLayer::new`](super::CsrfLayer::new).
26///
27/// Produces a `403 Forbidden` response with an empty body. The originating [`ProtectionError`] is
28/// attached to the response's extensions by [`Csrf`] itself, so it is present regardless of which
29/// builder produced the response.
30///
31/// [`Csrf`]: super::Csrf
32#[derive(Clone, Copy, Debug, Default)]
33#[non_exhaustive]
34pub struct DefaultResponseForProtectionError;
35
36impl<B: Default> ResponseForProtectionError<B> for DefaultResponseForProtectionError {
37    fn response_for_protection_error(&self, _error: ProtectionError) -> Response<B> {
38        let mut response = Response::new(B::default());
39        *response.status_mut() = StatusCode::FORBIDDEN;
40        response
41    }
42}