Skip to main content

ullun/
middleware.rs

1//! Middleware types and traits
2
3use crate::error::{Error, Result};
4use crate::request::Request;
5use crate::response::Response;
6use async_trait::async_trait;
7use std::sync::Arc;
8
9/// Middleware trait
10#[async_trait]
11pub trait Middleware: Send + Sync + 'static {
12    async fn handle(&self, req: Request, next: Next) -> Result<Response>;
13}
14
15/// Next middleware in chain
16#[derive(Clone)]
17pub struct Next {
18    middlewares: Arc<Vec<Arc<dyn Middleware>>>,
19    index: usize,
20}
21
22impl Next {
23    pub fn new(middlewares: Arc<Vec<Arc<dyn Middleware>>>) -> Self {
24        Self {
25            middlewares,
26            index: 0,
27        }
28    }
29
30    pub async fn run(mut self, req: Request) -> Result<Response> {
31        if self.index < self.middlewares.len() {
32            let middleware = self.middlewares[self.index].clone();
33            self.index += 1;
34            middleware.handle(req, self).await
35        } else {
36            // End of chain without handler match
37            Err(Error::not_found("Route not found"))
38        }
39    }
40}
41
42/// Share one middleware instance between several registrations, e.g. a
43/// `RateLimiter` whose budget spans multiple groups
44#[async_trait]
45impl<M: Middleware + ?Sized> Middleware for Arc<M> {
46    async fn handle(&self, req: Request, next: Next) -> Result<Response> {
47        (**self).handle(req, next).await
48    }
49}
50
51/// A handler wrapped in its own middleware stack (used by route groups)
52pub(crate) struct Layered {
53    middlewares: Vec<Arc<dyn Middleware>>,
54    inner: crate::handler::DynHandler,
55}
56
57impl Layered {
58    pub(crate) fn new(
59        middlewares: Vec<Arc<dyn Middleware>>,
60        inner: crate::handler::DynHandler,
61    ) -> Self {
62        Self { middlewares, inner }
63    }
64}
65
66#[async_trait]
67impl crate::handler::Handler for Layered {
68    async fn call(&self, req: Request) -> Result<Response> {
69        let inner = self.inner.clone();
70        let mut chain = self.middlewares.clone();
71        chain.push(Arc::new(move |req: Request, _next: Next| {
72            let inner = inner.clone();
73            async move { inner.call(req).await }
74        }));
75        Next::new(Arc::new(chain)).run(req).await
76    }
77}
78
79/// Implement Middleware for async functions
80#[async_trait]
81impl<F, Fut> Middleware for F
82where
83    F: Fn(Request, Next) -> Fut + Send + Sync + 'static,
84    Fut: std::future::Future<Output = Result<Response>> + Send + 'static,
85{
86    async fn handle(&self, req: Request, next: Next) -> Result<Response> {
87        (self)(req, next).await
88    }
89}
90
91/// Logger middleware
92pub async fn logger(req: Request, next: Next) -> Result<Response> {
93    let method = req.method.clone();
94    let uri = req.uri.clone();
95    let start = std::time::Instant::now();
96
97    let response = next.run(req).await;
98
99    let duration = start.elapsed();
100    println!("{} {} - {:?}", method, uri, duration);
101
102    response
103}
104
105/// CORS middleware with preflight support
106///
107/// Kept for compatibility; delegates to [`crate::cors::Cors`], which also fixes
108/// the old behaviour of answering every origin with the first configured one.
109#[deprecated(since = "0.4.4", note = "use ullun::cors::Cors")]
110pub fn cors(
111    allowed_origins: Vec<String>,
112) -> impl Fn(
113    Request,
114    Next,
115) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Response>> + Send>>
116       + Clone {
117    let cors = if allowed_origins.iter().any(|o| o == "*") {
118        crate::cors::Cors::new().allow_any_origin()
119    } else {
120        crate::cors::Cors::new()
121            .allow_origins(allowed_origins)
122            .allow_credentials()
123    };
124    let cors = Arc::new(cors);
125    move |req: Request, next: Next| {
126        let cors = cors.clone();
127        Box::pin(async move { cors.handle(req, next).await })
128    }
129}