cyfs_debug/log_util/
tide_log_middleware.rs

1use std::future::Future;
2use std::pin::Pin;
3use tide::{Middleware, Next, Request, Response};
4
5/// Log all incoming requests and responses.
6///
7/// This middleware is enabled by default in Tide.
8///
9/// # Examples
10///
11/// ```
12/// let mut app = tide::Server::new();
13/// app.middleware(tide::log::LogMiddleware::new());
14/// ```
15#[derive(Debug, Default, Clone)]
16pub struct LogMiddleware {
17    _priv: (),
18}
19
20impl LogMiddleware {
21    /// Create a new instance of `LogMiddleware`.
22    #[must_use]
23    pub fn new() -> Self {
24        Self { _priv: () }
25    }
26
27    /// Log a request and a response.
28    async fn log<'a, State: Send + Sync + Clone + 'static>(
29        &'a self,
30        ctx: Request<State>,
31        next: Next<'a, State>,
32    ) -> tide::Result {
33        let path = ctx.url().path().to_owned();
34        let method = ctx.method().to_string();
35        log::info!("<-- Request received {} {}", method, path);
36        let start = std::time::Instant::now();
37        let res = next.run(ctx).await;
38
39        let status = res.status();
40        if status.is_server_error() {
41            log::error!(
42                "--> Response sent {} {} {} {}",
43                method,
44                path,
45                status,
46                format!("{:?}", start.elapsed())
47            );
48        } else if status.is_client_error() {
49            log::warn!(
50                "--> Response sent {} {} {} {}",
51                method,
52                path,
53                status,
54                format!("{:?}", start.elapsed())
55            );
56        } else {
57            log::debug!(
58                "--> Response sent {} {} {} {}",
59                method,
60                path,
61                status,
62                format!("{:?}", start.elapsed())
63            );
64        }
65        Ok(res)
66    }
67}
68
69type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
70
71impl<State: Send + Sync + Clone + 'static> Middleware<State> for LogMiddleware {
72    fn handle<'a, 'b, 't>(
73        &'a self,
74        ctx: Request<State>,
75        next: Next<'b, State>,
76    ) -> BoxFuture<'t, tide::Result<Response>>
77    where
78        'a: 't,
79        'b: 't,
80        Self: 't,
81    {
82        Box::pin(async move { self.log(ctx, next).await })
83    }
84}