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
use crate::{Body, Request, Response, Result};

/// The `Middleware` trait is implemented by middleware structs.
///
/// It is used to intercept requests and responses. And optionally to modify them.
///
/// Example:
///
/// ```
/// # use swim_core::{Middleware, Request, Response, Result, Body};
///
/// #[derive(Debug)]
/// struct Logger;
///
/// #[async_trait::async_trait]
/// impl Middleware for Logger {
///     async fn pre(&self, request: Request<Body>) -> Result<Request<Body>> {
///         println!("New request: {:?}", request.uri());
///
///         Ok(request)
///     }
///
///     async fn post(&self, response: Response<Body>) -> Result<Response<Body>> {
///         println!("Response: {:?}", response.status());
///
///         Ok(response)
///     }
/// }
/// ```
///
/// Default implementations simply return the request and response without modifying them. You can override these methods to provide custom implementations.
#[async_trait::async_trait]
pub trait Middleware: std::fmt::Debug + Send + Sync + 'static {
    /// Called before the request is handled.
    ///
    /// The middleware can modify the request before it is handled by any apps.
    async fn pre(&self, request: Request<Body>) -> Result<Request<Body>> {
        Ok(request)
    }

    /// Called after the request has been handled.
    ///
    /// The middleware can modify the response before it is sent to the client.
    async fn post(&self, response: Response<Body>) -> Result<Response<Body>> {
        Ok(response)
    }
}

/// Allows a `Middleware` to be converted into a `Box<dyn Middleware>`.
///
/// Facilitates the use of the `into` method.
impl<M: Middleware + 'static> From<M> for Box<dyn Middleware> {
    fn from(middleware: M) -> Self {
        Box::new(middleware)
    }
}