soph_server/router/
mod.rs

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use crate::{traits::MiddlewareTrait, Middleware};

// https://github.com/tower-rs/tower/issues/496
#[derive(Default)]
pub struct Router {
    inner: axum::Router,
    middlewares: Vec<(String, Middleware)>,
}

impl Router {
    pub fn new() -> Self {
        #[allow(unused_mut)]
        let mut router = Self::default();

        // todo need runtime
        // https://github.com/tokio-rs/axum/issues/2634
        // #[cfg(feature = "middleware-rate-limit")]
        // router = router.middleware::<crate::middleware::RateLimit>();

        #[cfg(feature = "middleware-fallback")]
        {
            router = router.middleware::<crate::middleware::Fallback>();
        }

        #[cfg(feature = "middleware-cors")]
        {
            router = router.middleware::<crate::middleware::Cors>();
        }

        #[cfg(feature = "middleware-body-limit")]
        {
            router = router.middleware::<crate::middleware::BodyLimit>();
        }

        #[cfg(feature = "middleware-asset")]
        {
            router = router.middleware::<crate::middleware::Asset>();
        }

        #[cfg(feature = "middleware-compression")]
        {
            router = router.middleware::<crate::middleware::Compression>();
        }

        #[cfg(feature = "middleware-decompression")]
        {
            router = router.middleware::<crate::middleware::Decompression>();
        }

        #[cfg(feature = "middleware-set-sensitive-request-headers")]
        {
            router = router.middleware::<crate::middleware::SetSensitiveRequestHeaders>();
        }

        #[cfg(feature = "middleware-request-id")]
        {
            router = router.middleware::<crate::middleware::RequestId>();
        }

        #[cfg(feature = "middleware-tracing")]
        {
            router = router.middleware::<crate::middleware::Tracing>();
        }

        #[cfg(feature = "middleware-catch-panic")]
        {
            router = router.middleware::<crate::middleware::CatchPanic>();
        }

        #[cfg(feature = "middleware-timeout")]
        {
            router = router.middleware::<crate::middleware::Timeout>();
        }

        router
    }

    pub fn route(mut self, path: &str, method_router: axum::routing::MethodRouter<()>) -> Self {
        self.inner = self.inner.route(path, method_router);

        self
    }

    pub fn middleware<T: MiddlewareTrait>(mut self) -> Self {
        self.middlewares.push((T::name(), T::handle()));

        self
    }
}

impl From<Router> for axum::Router {
    fn from(mut value: Router) -> Self {
        let mut router = value.inner;
        let mut middlewares = vec![];

        while let Some((name, layer)) = value.middlewares.pop() {
            router = layer(router)
                .unwrap_or_else(|err| panic!("[middleware] `{name}` applied error: {err}"));

            middlewares.push(name);
        }

        while let Some(middleware) = middlewares.pop() {
            tracing::info!("[middleware] `{middleware}` successfully applied"); // todo different route may has different middlewares
        }

        router
    }
}