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}