swim_core/
middleware.rs

1use hyper::body::HttpBody;
2
3use crate::{request_info, response_info, Body, Request, Response, Result};
4
5/// The `Middleware` trait is implemented by middleware structs.
6///
7/// It is used to intercept requests and responses. And optionally to modify them.
8///
9/// Example:
10///
11/// ```
12/// # use swim_core::{Middleware, Request, Response, Result, Body};
13///
14/// #[derive(Debug)]
15/// struct Logger;
16///
17/// #[async_trait::async_trait]
18/// impl Middleware for Logger {
19///     async fn pre(&self, request: Request<Body>) -> Result<Request<Body>> {
20///         println!("New request: {:?}", request.uri());
21///
22///         Ok(request)
23///     }
24///
25///     async fn post(&self, response: Response<Body>) -> Result<Response<Body>> {
26///         println!("Response: {:?}", response.status());
27///
28///         Ok(response)
29///     }
30/// }
31/// ```
32///
33/// Default implementations simply return the request and response without modifying them. You can override these methods to provide custom implementations.
34#[async_trait::async_trait]
35pub trait Middleware: std::fmt::Debug + Send + Sync + 'static {
36    /// Called before the request is handled.
37    ///
38    /// The middleware can modify the request before it is handled by any apps.
39    async fn pre(&self, request: Request<Body>) -> Result<Request<Body>> {
40        Ok(request)
41    }
42
43    /// Called after the request has been handled.
44    ///
45    /// The middleware can modify the response before it is sent to the client.
46    async fn post(&self, response: Response<Body>) -> Result<Response<Body>> {
47        Ok(response)
48    }
49}
50
51/// Allows a `Middleware` to be converted into a `Box<dyn Middleware>`.
52///
53/// Facilitates the use of the `into` method.
54impl<M: Middleware + 'static> From<M> for Box<dyn Middleware> {
55    fn from(middleware: M) -> Self {
56        Box::new(middleware)
57    }
58}
59
60/// A built-in middleware that logs requests and responses.
61///
62/// This middleware is enabled by default.
63#[derive(Debug)]
64pub struct Logger;
65
66#[async_trait::async_trait]
67impl Middleware for Logger {
68    async fn pre(&self, request: Request<Body>) -> Result<Request<Body>> {
69        request_info!(request);
70
71        Ok(request)
72    }
73
74    async fn post(&self, response: Response<Body>) -> Result<Response<Body>> {
75        response_info!(response);
76
77        Ok(response)
78    }
79}