credence_lib/middleware/
defer.rs

1use {
2    axum::{
3        extract::Request,
4        http::{header::*, *},
5        response::{Response, *},
6    },
7    kutil::std::immutable::*,
8};
9
10//
11// DeferredResponse
12//
13
14/// Deferred response as a [Request] extension.
15#[derive(Clone, Debug)]
16pub enum DeferredResponse {
17    /// Hide.
18    Hide,
19
20    /// Authenticate.
21    Authenticate(ByteString),
22
23    /// Redirect to URI path.
24    RedirectTo((ByteString, StatusCode)),
25
26    /// Rewrite from URI path.
27    RewriteFrom(ByteString),
28
29    /// Error.
30    Error(ByteString),
31}
32
33impl DeferredResponse {
34    /// Get.
35    pub fn get(request: &Request) -> Option<&Self> {
36        request.extensions().get()
37    }
38
39    /// Authentication response.
40    ///
41    /// [StatusCode::UNAUTHORIZED] with a `WWW-Authenticate` header value.
42    pub fn authenticate(authenticate: &str) -> Response {
43        (StatusCode::UNAUTHORIZED, [(WWW_AUTHENTICATE, authenticate)]).into_response()
44    }
45
46    /// Redirection response.
47    ///
48    /// [StatusCode::MOVED_PERMANENTLY] with a `Location` header value.
49    pub fn redirect_to(uri_path: &str, status_code: StatusCode) -> Response {
50        assert!(status_code.is_redirection());
51        (status_code, [(LOCATION, uri_path)]).into_response()
52    }
53}
54
55//
56// WithDeferredResponse
57//
58
59/// With [DeferredResponse].
60pub trait WithDeferredResponse {
61    /// With [DeferredResponse].
62    fn with_deferred_response(self, delayed_response: DeferredResponse) -> Self;
63
64    /// With [DeferredResponse::Hide].
65    fn with_deferred_hide(self) -> Self;
66
67    /// With [DeferredResponse::Authenticate].
68    fn with_deferred_authenticate(self, authenticate: ByteString) -> Self;
69
70    /// With [DeferredResponse::RedirectTo].
71    fn with_deferred_redirect_to(self, uri_path: ByteString, status_code: StatusCode) -> Self;
72
73    /// With [DeferredResponse::RewriteFrom].
74    fn with_deferred_rewrite_from(self, uri_path: ByteString) -> Self;
75
76    /// With [DeferredResponse::Error].
77    fn with_deferred_error(self, error: ByteString) -> Self;
78}
79
80impl WithDeferredResponse for Request {
81    fn with_deferred_response(mut self, delayed_response: DeferredResponse) -> Self {
82        self.extensions_mut().insert(delayed_response);
83        self
84    }
85
86    fn with_deferred_hide(self) -> Self {
87        self.with_deferred_response(DeferredResponse::Hide)
88    }
89
90    fn with_deferred_authenticate(self, authenticate: ByteString) -> Self {
91        self.with_deferred_response(DeferredResponse::Authenticate(authenticate))
92    }
93
94    fn with_deferred_redirect_to(self, uri_path: ByteString, status_code: StatusCode) -> Self {
95        assert!(status_code.is_redirection());
96        self.with_deferred_response(DeferredResponse::RedirectTo((uri_path, status_code)))
97    }
98
99    fn with_deferred_rewrite_from(self, uri_path: ByteString) -> Self {
100        self.with_deferred_response(DeferredResponse::RewriteFrom(uri_path))
101    }
102
103    fn with_deferred_error(self, error: ByteString) -> Self {
104        self.with_deferred_response(DeferredResponse::Error(error))
105    }
106}